题意:
给定一个长度为 n 的非负数列,定义 mex(l, r) 为 l,r 区间里最小的没有出现的数字。
求所有 mex(l, r) 的和
分析参见 http://www.shuizilong.com/house/archives/hdu-4747-mex/
我的代码:
1 #include <cstdio>
2 #include <algorithm>
3 #include <cstring>
4 #include <vector>
5 typedef long long ll;
6 #define lson l, mid, rt << 1
7 #define rson mid + 1, r, rt << 1 |1
8
9 struct node {
10 int mx, mi, setv;
11 ll sum;
12 };
13
14 const int N = 200000 + 10;
15 int ar[N];
16 node seg[N << 2];
17
18 bool vis[N];
19 int idx;
20
21 void Up(node& fa, node& ls, node& rs) {
22 fa.mx = std::max(ls.mx , rs.mx);
23 fa.sum = ls.sum + rs.sum;
24 fa.mi = std::min(ls.mi, rs.mi);
25 }
26 void build(int l, int r, int rt) {
27 seg[rt].setv = -1;
28 if (l == r) {
29 vis[ar[l]] = true;
30 while (vis[idx])
31 ++idx;
32 seg[rt].mx = seg[rt].mi = seg[rt].sum = idx;
33 } else {
34 int mid = (l + r) >> 1;
35 build(lson);
36 build(rson);
37 Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]);
38 }
39 }
40 void Down(node& fa, node& ls, node& rs, int len) {
41 if (~fa.setv) {
42 ls.setv = rs.setv = ls.mx = rs.mx = ls.mi = rs.mi = fa.setv;
43 ls.sum = (ll)(len - (len >> 1)) * fa.setv;
44 rs.sum = (ll)(len >> 1) * fa.setv;
45 fa.setv = -1;
46 }
47 }
48 ll query(int L, int R, int l, int r, int rt) {
49 if (L == l && R == r)
50 return seg[rt].sum;
51 Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1], r - l + 1);
52 int mid = (l + r) >> 1;
53 if (R <= mid) return query(L, R, lson);
54 else if (L > mid) return query(L, R, rson);
55 else return query(L, mid, lson) + query(mid + 1, R, rson);
56 }
57 void update(int L, int R, int v, int l, int r, int rt) {
58 if (seg[rt].mx <= v) return ;
59 int mid = (l + r) >> 1;
60 if (L == l && R == r) {
61 if (seg[rt].mi >= v) {
62 seg[rt].mi = seg[rt].mx = seg[rt].setv = v;
63 seg[rt].sum = (ll)(r - l + 1) * v;
64 return ;
65 }
66 if (l == r) {
67 if (seg[rt].mx > v) {
68 seg[rt].mi = seg[rt].mx = seg[rt].sum = v;
69 seg[rt].setv = -1;
70 }
71 return ;
72 }
73 //
74 Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1], r - l + 1);
75 if (R <= mid) update(L, R, v, lson);
76 else if (L > mid) update(L, R, v, rson);
77 else {
78 update(L, mid, v, lson);
79 update(mid + 1, R, v, rson);
80 }
81 Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]);
82 //
83 } else {
84 Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1], r - l + 1);
85 if (R <= mid) update(L, R, v, lson);
86 else if (L > mid) update(L, R, v, rson);
87 else {
88 update(L, mid, v, lson);
89 update(mid + 1, R, v, rson);
90 }
91 Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]);
92 }
93 }
94 int n;
95
96 int nex[N], hap[N];
97
98 void work() {
99 for (int i = 1; i <= n; ++i) {
100 scanf("%d", &ar[i]);
101 if (ar[i] > n)
102 ar[i] = n + 1;
103 }
104 memset(vis, 0, sizeof(vis));
105 idx = 0;
106 build(1, n, 1);
107 ll ans = query(1, n, 1, n, 1);
108
109 memset(hap, -1, sizeof(hap));
110 memset(nex, -1, sizeof(nex));
111
112 for (int i = 1; i <= n; ++i) {
113 if (hap[ar[i]] == -1)
114 hap[ar[i]] = i;
115 else {
116 nex[hap[ar[i]]] = i;
117 hap[ar[i]] = i;
118 }
119 }
120
121 int to;
122 for (int i = 1; i <= n - 1; ++i) {
123 if (nex[i] == -1)
124 to = n;
125 else
126 to = nex[i] - 1;
127 update(i, to, ar[i], 1, n, 1);
128 ans = ans + query(i, n, 1, n, 1);
129 }
130 printf("%I64d ", ans);
131 }
132 int main() {
133 while (1 == scanf("%d", &n)) {
134 if (0 == n) break;
135 work();
136 }
137 return 0;
138 }
2 #include <algorithm>
3 #include <cstring>
4 #include <vector>
5 typedef long long ll;
6 #define lson l, mid, rt << 1
7 #define rson mid + 1, r, rt << 1 |1
8
9 struct node {
10 int mx, mi, setv;
11 ll sum;
12 };
13
14 const int N = 200000 + 10;
15 int ar[N];
16 node seg[N << 2];
17
18 bool vis[N];
19 int idx;
20
21 void Up(node& fa, node& ls, node& rs) {
22 fa.mx = std::max(ls.mx , rs.mx);
23 fa.sum = ls.sum + rs.sum;
24 fa.mi = std::min(ls.mi, rs.mi);
25 }
26 void build(int l, int r, int rt) {
27 seg[rt].setv = -1;
28 if (l == r) {
29 vis[ar[l]] = true;
30 while (vis[idx])
31 ++idx;
32 seg[rt].mx = seg[rt].mi = seg[rt].sum = idx;
33 } else {
34 int mid = (l + r) >> 1;
35 build(lson);
36 build(rson);
37 Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]);
38 }
39 }
40 void Down(node& fa, node& ls, node& rs, int len) {
41 if (~fa.setv) {
42 ls.setv = rs.setv = ls.mx = rs.mx = ls.mi = rs.mi = fa.setv;
43 ls.sum = (ll)(len - (len >> 1)) * fa.setv;
44 rs.sum = (ll)(len >> 1) * fa.setv;
45 fa.setv = -1;
46 }
47 }
48 ll query(int L, int R, int l, int r, int rt) {
49 if (L == l && R == r)
50 return seg[rt].sum;
51 Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1], r - l + 1);
52 int mid = (l + r) >> 1;
53 if (R <= mid) return query(L, R, lson);
54 else if (L > mid) return query(L, R, rson);
55 else return query(L, mid, lson) + query(mid + 1, R, rson);
56 }
57 void update(int L, int R, int v, int l, int r, int rt) {
58 if (seg[rt].mx <= v) return ;
59 int mid = (l + r) >> 1;
60 if (L == l && R == r) {
61 if (seg[rt].mi >= v) {
62 seg[rt].mi = seg[rt].mx = seg[rt].setv = v;
63 seg[rt].sum = (ll)(r - l + 1) * v;
64 return ;
65 }
66 if (l == r) {
67 if (seg[rt].mx > v) {
68 seg[rt].mi = seg[rt].mx = seg[rt].sum = v;
69 seg[rt].setv = -1;
70 }
71 return ;
72 }
73 //
74 Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1], r - l + 1);
75 if (R <= mid) update(L, R, v, lson);
76 else if (L > mid) update(L, R, v, rson);
77 else {
78 update(L, mid, v, lson);
79 update(mid + 1, R, v, rson);
80 }
81 Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]);
82 //
83 } else {
84 Down(seg[rt], seg[rt << 1], seg[rt << 1 | 1], r - l + 1);
85 if (R <= mid) update(L, R, v, lson);
86 else if (L > mid) update(L, R, v, rson);
87 else {
88 update(L, mid, v, lson);
89 update(mid + 1, R, v, rson);
90 }
91 Up(seg[rt], seg[rt << 1], seg[rt << 1 | 1]);
92 }
93 }
94 int n;
95
96 int nex[N], hap[N];
97
98 void work() {
99 for (int i = 1; i <= n; ++i) {
100 scanf("%d", &ar[i]);
101 if (ar[i] > n)
102 ar[i] = n + 1;
103 }
104 memset(vis, 0, sizeof(vis));
105 idx = 0;
106 build(1, n, 1);
107 ll ans = query(1, n, 1, n, 1);
108
109 memset(hap, -1, sizeof(hap));
110 memset(nex, -1, sizeof(nex));
111
112 for (int i = 1; i <= n; ++i) {
113 if (hap[ar[i]] == -1)
114 hap[ar[i]] = i;
115 else {
116 nex[hap[ar[i]]] = i;
117 hap[ar[i]] = i;
118 }
119 }
120
121 int to;
122 for (int i = 1; i <= n - 1; ++i) {
123 if (nex[i] == -1)
124 to = n;
125 else
126 to = nex[i] - 1;
127 update(i, to, ar[i], 1, n, 1);
128 ans = ans + query(i, n, 1, n, 1);
129 }
130 printf("%I64d ", ans);
131 }
132 int main() {
133 while (1 == scanf("%d", &n)) {
134 if (0 == n) break;
135 work();
136 }
137 return 0;
138 }
CLJ有一个很诡异的map解法
1 #include <vector>
2 #include <string>
3 #include <iostream>
4 #include <algorithm>
5 #include <queue>
6 #include <set>
7 #include <map>
8 #include <sstream>
9 #include <iomanip>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 #include <cmath>
14 using namespace std;
15 typedef long long ll;
16 typedef double du;
17 #define pb push_back
18 #define mp make_pair
19 #define fi first
20 #define se second
21 #define FOR(i, s, t) for(i = (s); i < (t); i++)
22 #define RFOR(i, s, t) for(i = (s)-1; i >= (t); i--)
23 const int MAXN = 200004;
24
25 int a[MAXN];
26 int nextSame[MAXN], next[MAXN];
27 bool vis[MAXN];
28 map<int, int> s;
29
30 int main()
31 {
32 #ifdef __FIO
33 freopen("in.txt", "r", stdin);
34 //freopen("out.txt", "w", stdout);
35 #endif
36 int T;
37 //scanf("%d", &T);
38 while(1){
39 int n;
40 int i, j, k;
41 int si;
42 ll sum, tsum;
43 sum = tsum = 0;
44 scanf("%d", &n);
45 if(n == 0)
46 break;
47 for(i = 0; i < n; i++){
48 scanf("%d", &a[i]);
49 if(a[i] > n)
50 a[i] = n+1;
51 }
52 for(i = 0; i <= n+1; i++)
53 next[i] = n;
54 for(i = n-1; i >= 0; i--){
55 nextSame[i] = next[a[i]];
56 next[a[i]] = i;
57 }
58 memset(vis, 0, sizeof vis);
59 j = 0;
60 s.clear();
61 for(i = 0; i < n; i++){
62 vis[a[i]] = true;
63 while(vis[j])
64 j++;
65 tsum += j;
66 s[i] = j;
67 }
68 s[n] = n;
69 sum += tsum;
70 for(i = 0; i < n-1; i++){
71 tsum -= s.begin()->se;
72 s[i] = -1;
73 map<int, int>::iterator it = s.lower_bound(nextSame[i]-1);
74 if(it->se > a[i]){
75 if(it->fi >= nextSame[i]){
76 int temp = it->se-a[i];
77 tsum -= (ll)temp*(nextSame[i]-1);
78 it--;
79 tsum += (ll)temp*it->fi;
80 }
81 while(it->se >= a[i]){
82 int temp = it->se-a[i];
83 tsum -= (ll)temp*it->fi;
84 s.erase(it--);
85 tsum += (ll)temp*it->fi;
86 }
87 s[nextSame[i]-1] = a[i];
88 }
89 s.erase(i);
90 sum += tsum;
91 }
92 printf("%I64d ", sum);
93 }
94 return 0;
95 }
2 #include <string>
3 #include <iostream>
4 #include <algorithm>
5 #include <queue>
6 #include <set>
7 #include <map>
8 #include <sstream>
9 #include <iomanip>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 #include <cmath>
14 using namespace std;
15 typedef long long ll;
16 typedef double du;
17 #define pb push_back
18 #define mp make_pair
19 #define fi first
20 #define se second
21 #define FOR(i, s, t) for(i = (s); i < (t); i++)
22 #define RFOR(i, s, t) for(i = (s)-1; i >= (t); i--)
23 const int MAXN = 200004;
24
25 int a[MAXN];
26 int nextSame[MAXN], next[MAXN];
27 bool vis[MAXN];
28 map<int, int> s;
29
30 int main()
31 {
32 #ifdef __FIO
33 freopen("in.txt", "r", stdin);
34 //freopen("out.txt", "w", stdout);
35 #endif
36 int T;
37 //scanf("%d", &T);
38 while(1){
39 int n;
40 int i, j, k;
41 int si;
42 ll sum, tsum;
43 sum = tsum = 0;
44 scanf("%d", &n);
45 if(n == 0)
46 break;
47 for(i = 0; i < n; i++){
48 scanf("%d", &a[i]);
49 if(a[i] > n)
50 a[i] = n+1;
51 }
52 for(i = 0; i <= n+1; i++)
53 next[i] = n;
54 for(i = n-1; i >= 0; i--){
55 nextSame[i] = next[a[i]];
56 next[a[i]] = i;
57 }
58 memset(vis, 0, sizeof vis);
59 j = 0;
60 s.clear();
61 for(i = 0; i < n; i++){
62 vis[a[i]] = true;
63 while(vis[j])
64 j++;
65 tsum += j;
66 s[i] = j;
67 }
68 s[n] = n;
69 sum += tsum;
70 for(i = 0; i < n-1; i++){
71 tsum -= s.begin()->se;
72 s[i] = -1;
73 map<int, int>::iterator it = s.lower_bound(nextSame[i]-1);
74 if(it->se > a[i]){
75 if(it->fi >= nextSame[i]){
76 int temp = it->se-a[i];
77 tsum -= (ll)temp*(nextSame[i]-1);
78 it--;
79 tsum += (ll)temp*it->fi;
80 }
81 while(it->se >= a[i]){
82 int temp = it->se-a[i];
83 tsum -= (ll)temp*it->fi;
84 s.erase(it--);
85 tsum += (ll)temp*it->fi;
86 }
87 s[nextSame[i]-1] = a[i];
88 }
89 s.erase(i);
90 sum += tsum;
91 }
92 printf("%I64d ", sum);
93 }
94 return 0;
95 }