HDU 4747 Mex(線分樹)
6285 ワード
転載は出典を明記してください.ありがとうございます. by---cxlove
題目:シーケンスを与え、mex{}はセットに出現しない最小の自然数を表します.それからsigma(mex(i,j)を求めます.
試合中、ボスに秒を奪われました.怖いですね.
作り方:左端点が固定されている場合の全区間のmex値を考慮して、このシーケンスは不再減です.まずは分かります
最初はmex[i]を求めてmex(1,i)を表しています.左の端点については、区間の合計です.
現在考慮されているのは、シーケンスに対する左端点の変化の影響である.
すなわち、左エンドポイントはi->>i+1、mex[j]から変化する.シーケンスに対するaiの影響を削除します.
a[j]=a[i]且つj>iの場合、a[k]=a[i]は存在しない. j>k>iつまりa[i]次の出現位置です.
mexの定義によって、mex[k]は変わらないと知っています.k>=j.削除されたaiはまだシーケンスに存在しますので、影響を受けません.
その後、i+1からj−1までの区間のmex値を考慮する必要があります.aiを削除したら、元のmex値がaiより大きいように、いずれもaiに更新されます.
よく分かります.出現していない最小のため、aiはもっと小さいです.
前に述べたように、これは非逓減シーケンスであり、元のmex値がa iよりも大きいのも連続的な区間であるため、最も左に近い位置rを見つけることができ、mex[r]a[i]を作ることができる.rからj-1までの区間のmex値はa[i]に更新される.
全部できました....線分樹でmexシーケンスを維持し、区間を更新し、区間を合計して検索すればいいです.
下のコードは私がボスのコードの中の線分の木の部分を書き直したものです.
題目:シーケンスを与え、mex{}はセットに出現しない最小の自然数を表します.それからsigma(mex(i,j)を求めます.
試合中、ボスに秒を奪われました.怖いですね.
作り方:左端点が固定されている場合の全区間のmex値を考慮して、このシーケンスは不再減です.まずは分かります
最初はmex[i]を求めてmex(1,i)を表しています.左の端点については、区間の合計です.
現在考慮されているのは、シーケンスに対する左端点の変化の影響である.
すなわち、左エンドポイントはi->>i+1、mex[j]から変化する.シーケンスに対するaiの影響を削除します.
a[j]=a[i]且つj>iの場合、a[k]=a[i]は存在しない. j>k>iつまりa[i]次の出現位置です.
mexの定義によって、mex[k]は変わらないと知っています.k>=j.削除されたaiはまだシーケンスに存在しますので、影響を受けません.
その後、i+1からj−1までの区間のmex値を考慮する必要があります.aiを削除したら、元のmex値がaiより大きいように、いずれもaiに更新されます.
よく分かります.出現していない最小のため、aiはもっと小さいです.
前に述べたように、これは非逓減シーケンスであり、元のmex値がa iよりも大きいのも連続的な区間であるため、最も左に近い位置rを見つけることができ、mex[r]a[i]を作ることができる.rからj-1までの区間のmex値はa[i]に更新される.
全部できました....線分樹でmexシーケンスを維持し、区間を更新し、区間を合計して検索すればいいです.
下のコードは私がボスのコードの中の線分の木の部分を書き直したものです.
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string>
#include <cstring>
using namespace std;
typedef unsigned int UI;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<bool> VB;
typedef vector<char> VC;
typedef vector<double> VD;
typedef vector<string> VS;
typedef vector<VI> VVI;
typedef vector<PII> VPII;
template <class T> inline void checkMin(T& a, T b) { if (b < a) a = b; }
template <class T> inline void checkMax(T& a, T b) { if (b > a) a = b; }
const int MOD = 1000000007;
const int dx[] = {0, -1, 0, 1};
const int dy[] = {1, 0, -1, 0};
bool cmp(const PII& a, const PII& b) {
if (a.first != b.first) return a.first < b.first;
else return a.second < b.second;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const int N = 200010;
PII b[N];
int n, m, a[N], vis[N], next[N];
#define lson step << 1
#define rson step << 1 | 1
struct Node {
int left , right;
int mx , lazy;
LL sum;
}L[N << 2];
void pushUp (int step) {
L[step].sum = L[lson].sum + L[rson].sum;
L[step].mx = max (L[lson].mx , L[rson].mx);
}
void update (int step , int l , int r , int w) ;
void pushDown (int step) {
int l = L[step].left , r = L[step].right , m = (l + r) >> 1;
int &z = L[step].lazy;
if (z != -1) {
update (lson , l , m , z);
update (rson , m + 1 ,r , z);
z = -1;
}
}
void bulid (int step , int l , int r) {
L[step].left = l;
L[step].right = r;
L[step].mx = L[step].sum = 0;
L[step].lazy = -1;
if (l == r) return ;
int m = (l + r) >> 1;
bulid (lson , l , m);
bulid (rson , m + 1 , r);
}
void update (int step , int p , int w) {
if (L[step].left == L[step].right) {
L[step].mx = L[step].sum = w;
return ;
}
pushDown (step);
int m = (L[step].left + L[step].right) >> 1;
if (p <= m) update (lson , p , w);
else update (rson , p , w);
pushUp (step);
}
void update (int step , int l , int r , int w) {
if (L[step].left == l && L[step].right == r) {
L[step].lazy = w;
L[step].mx = w;
L[step].sum = (r - l + 1) * 1LL * w;
return ;
}
pushDown (step);
int m = (L[step].left + L[step].right) >> 1;
if (r <= m) update (lson , l , r , w);
else if (l > m) update (rson , l , r , w);
else {
update (lson , l , m , w);
update (rson , m + 1 , r , w);
}
pushUp (step);
}
int queryp (int step , int w) {
if (L[step].mx <= w) return n + 1;
if (L[step].left == L[step].right) return L[step].left;
pushDown (step);
int m = (L[step].left + L[step].right) >> 1;
if (L[lson].mx > w) return queryp (lson , w);
else return queryp (rson , w);
}
LL querys (int step , int l , int r) {
if (L[step].left == l && L[step].right == r)
return L[step].sum ;
pushDown (step);
int m = (L[step].left + L[step].right) >> 1;
if (r <= m) return querys (lson , l , r);
else if (l > m) return querys (rson , l , r);
else return querys (lson , l , m) + querys (rson , m + 1 , r);
}
int main() {
#ifndef ONLINE_JUDGE
freopen ("input.txt" , "r" , stdin);
// freopen ("output.txt" , "w" , stdout);
#endif
while (scanf("%d", &n) != EOF && n != 0) {
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = make_pair(a[i], i);
next[i] = n + 1;
vis[i] = false;
}
vis[0] = false;
sort(b + 1, b + n + 1, cmp);
b[n + 1].first = b[n].first, b[n + 1].second = n + 1;
for (int i = 1; i <= n; i++) {
if (b[i + 1].first == b[i].first) next[b[i].second] = b[i + 1].second;
}
bulid (1 , 1 , n);
int mmex = 0;
for (int i = 1; i <= n; i++) {
if (a[i] <= n) vis[a[i]] = true;
while (vis[mmex]) mmex++;
update(1 , i, mmex);
}
LL ans = 0;
a[0] = n + 1; next[0] = n + 1;
for (int l = 1; l <= n; l++) {
if (a[l - 1] <= mmex) {
int p0 = queryp(1 ,a[l - 1]);
if (p0 != -1)
p0 = max (p0, l);
int p1 = next[l - 1];
if (p0 >= l && p0 < p1)
update(1 ,p0 , p1 - 1 , a[l - 1]);
}
ans += querys(1 , l, n);
}
printf("%I64d
", ans);
}
return 0