The meaning of problems:
given \ (n-\) number, and seeking \ (\ sum_. 1} ^ {n-I = \ sum_ {J} = I ^ nmex (I, J) \) . \ (mex (i, j) \) representing the interval \ ([i, j] \ ) a \ (MEX \) .
Ideas:
- Consider about enumeration endpoint of one of them, then quickly answers statistics.
- Observed for a (\ a_i) \ , if the interval left endpoint from containing it to a state not included, then it will affect the \ ([i + 1, next [a_i] -1] \) of this section in the \ (MEX \) value.
- So try to enumerate the left point, according to the answer quickly left the statistical point value. (A start point for a long time wanted to get out of the right end of ah = =)
- Statistical how it?
- Observed to the left end point fixed, the interval \ (mex \) is nondecreasing, then we take advantage of this property!
- Find the point located right \ ([i + 1, next [a_i] -1] \) , the interval \ (MEX \) is greater than \ (a_i \) is set, and then to modify the range.
Overall, mainly to analyze to a point on the interval \ (mex \) effects, as well as the interval \ (mex \) monotony.
#include <bits/stdc++.h>
//#define heyuhhh ok
using namespace std;
typedef long long ll;
const int N = 200005;
int a[N], b[N];
int n;
bool vis[N];
ll sumv[N << 2], lz[N << 2], maxv[N << 2];
int nxt[N];
void Getmex() {
map <int, int> mp;
int j = 0;
for(int i = 0; i <= n + 1; i++) vis[i] = 0;
for(int i = 1; i <= n; i++) {
if(a[i] <= n) vis[a[i]] = 1;
while(vis[j]) ++j;
b[i] = j;
}
for(int i = n; i >= 1; i--) {
if(mp.find(a[i]) == mp.end()) nxt[i] = n + 1;
else nxt[i] = mp[a[i]];
mp[a[i]] = i;
}
}
void push_up(int o) {
sumv[o] = sumv[o << 1] + sumv[o << 1|1];
maxv[o] = max(maxv[o << 1], maxv[o << 1|1]);
}
void push_down(int o, int l, int r) {
if(lz[o] != -1) {
int mid = (l + r) >> 1;
lz[o << 1] = lz[o << 1|1] = lz[o];
sumv[o << 1] = 1ll * (mid - l + 1) * lz[o];
sumv[o << 1|1] = 1ll * (r - mid) * lz[o];
maxv[o << 1] = maxv[o << 1|1] = lz[o];
lz[o] = -1;
}
}
void build(int o, int l, int r) {
lz[o] = -1;
if(l == r) {
sumv[o] = maxv[o] = b[l];
return;
}
int mid = (l + r) >> 1;
build(o << 1, l, mid); build(o << 1|1, mid + 1, r);
push_up(o);
}
int query_l(int o, int l, int r, int L, int R, int v) {
if(l == r) return l;
int mid = (l + r) >> 1;
push_down(o, l, r);
int ok = -1;
if(maxv[o << 1] >= v && L <= mid) ok = query_l(o << 1, l, mid, L, R, v);
if(ok == -1 && maxv[o << 1|1] >= v && R > mid) ok = query_l(o << 1|1, mid + 1, r, L, R, v);
return ok;
}
void update(int o, int l, int r, int L, int R, int v) {
if(L <= l && r <= R) {
lz[o] = v;
sumv[o] = 1ll * (r - l + 1) * v;
maxv[o] = v;
return;
}
push_down(o, l, r);
int mid = (l + r) >> 1;
if(L <= mid) update(o << 1, l, mid, L, R, v);
if(R > mid) update(o << 1|1, mid + 1, r, L, R, v);
push_up(o);
}
ll query(int o, int l, int r, int L, int R) {
if(L <= l && r <= R) {
return sumv[o];
}
push_down(o, l, r);
int mid = (l + r) >> 1;
ll res = 0;
if(L <= mid) res += query(o << 1, l, mid, L, R);
if(R > mid) res += query(o << 1|1, mid + 1, r, L, R);
return res;
}
int main() {
while(cin >> n && n) {
for(int i = 1; i <= n; i++) cin >> a[i];
Getmex();
build(1, 1, n);
ll ans = query(1, 1, n, 1, n);
for(int i = 1; i < n; i++) {
int Next = nxt[i] - 1;
int L = query_l(1, 1, n, i + 1, Next, a[i]);
if(L != -1) update(1, 1, n, L, Next, a[i]);
ans += query(1, 1, n, i + 1, n);
}
cout << ans << '\n';
}
return 0;
}