Brief description:
。。。给定一个长度为 n 的非负数列。。定义 mex(l, r) 为 l,r 区间里最小的没有出现的数字。
。。求所有 mex(l, r) 的和。。。
Analysis:
..。直接合并区间难以进行时。。利用离线先固定一个端点。。沿着另一个端点扫应该是接下来第一个要想的方法了。。。
。艹。。我是傻逼么。。
。。先 O(n) 搞出 mex1[i] 表示初始的 mex(1, i)。。这个是单调递增的。。。
。。。再 O(n) 搞出每个 nxt[i] 。。表示右边第一个和 i 相同的位置。。(如果没有则等于 n+1。。。。
。。。接着沿着左侧开始删除。。删除前要统计出以这个点为左端点的所有 mex。 。。
。。。考虑删除 a[i]。。那么将 i+1 到 nxt[i]-1 之间。。mex 大于 a[i] 的全设置成 a[i]。即可。。。
。。。于是我们需要维护。。。区间求和。。。以及区间赋值成至多 a[i]。。。这是一个线段树的 Open Problem 。。。(至少对我而言。?。。
。。。进一步分析发现 mex 始终是单调递增的。。
。。。因此将 i+1 到 nxt[i]-1 赋值到至多 a[i]。。就是将第一个大于 a[i] 的位置 到 nxt[i] -1 赋值到 a[i] 即可。。而这是一个线段树入门级别的操作。。。
const int N = 200009, NN = 4*N;
int A[N], C[N], nxt[N], mex1[N];
int n;
LL ss[NN]; int mx[NN]; bool dd[NN]; int a, b, c;
#define root 1, 1, n
#define lx (x << 1)
#define rx (lx | 1)
#define ml (l + r >> 1)
#define mr (ml + 1)
#define len (r - l + 1)
#define xc x, l, r
#define lc lx, l, ml
#define rc rx, mr, r
inline void Apply_Cov(int x, int l, int r, int val){
    mx[x] = val, ss[x] = (LL) len * val, dd[x] = 1;
}
void Release(int x, int l, int r){
    if (dd[x]){
        Apply_Cov(lc, mx[x]), Apply_Cov(rc, mx[x]);
        dd[x] = 0;
    }
}
void Update(int x){
    mx[x] = max(mx[lx], mx[rx]);
    ss[x] = ss[lx] + ss[rx];
}
void Insert(int x, int l, int r){
    if (b < l || r < a) return;
    if (a <= l && r <= b){
        Apply_Cov(xc, c);
    }
    else{
        Release(xc);
        Insert(lc), Insert(rc);
        Update(x);
    }
}
int Upper_Bound(int x, int l, int r){
    if (l == r) return l;
    else{
        Release(xc);
        return mx[lx] > c ? Upper_Bound(lc) : Upper_Bound(rc);
    }
}
void Build(int x, int l, int r){
    dd[x] = 0; if (l == r) mx[x] = ss[x] = mex1[l];
    else Build(lc), Build(rc), Update(x);
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    while (RD(n)){
        REP_1_C(i, n)  checkMin(RD(A[i]), 200001);
        int mex = 0; RST(C); REP_1(i, n){
            ++C[A[i]]; while (C[mex]) ++mex;
            mex1[i] = mex;
        }
        fill(C, C+N, n+1); DWN_1(i, n, 1){
            nxt[i] = C[A[i]];
            C[A[i]] = i;
        }
        LL res = 0; Build(root); REP_1(i, n){
            res += ss[1]; if (mx[1] > A[i]){
                c = A[i], a = Upper_Bound(root), b = nxt[i]-1; if (a <= b) Insert(root);
            }
            a = i, b = i, c = 0, Insert(root);
            if (!mx[1]) break;
        }
        OT(res);
    }
}




 Alca
 Alca Amber
 Amber Belleve Invis
 Belleve Invis Chensiting123
 Chensiting123 Edward_mj
 Edward_mj Fotile96
 Fotile96 Hlworld
 Hlworld Kuangbin
 Kuangbin Liyaos
 Liyaos Lwins
 Lwins LYPenny
 LYPenny Mato 完整版
 Mato 完整版 Mikeni2006
 Mikeni2006 Mzry
 Mzry Nagatsuki
 Nagatsuki Neko13
 Neko13 Oneplus
 Oneplus Rukata
 Rukata Seter
 Seter Sevenkplus
 Sevenkplus Sevenzero
 Sevenzero Shirleycrow
 Shirleycrow Vfleaking
 Vfleaking wangzhpp
 wangzhpp Watashi
 Watashi WJMZBMR
 WJMZBMR Wywcgs
 Wywcgs XadillaX
 XadillaX Yangzhe
 Yangzhe 三途川玉子
 三途川玉子 About.me
 About.me Vijos
 Vijos
