[2013 ACM/ICPC Asia Regional Hangzhou Online J/1010]hdu 4747 Mex (线段树)

题意:

给定一个长度为 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, 0sizeof(vis));
105     idx = 0;
106     build(1, n, 1);
107     ll ans = query(1, n, 1, n, 1);
108 
109     memset(hap, -1sizeof(hap));
110     memset(nex, -1sizeof(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\n", ans);
131 }
132 int main() {
133     while (1 == scanf("%d", &n)) {
134         if (0 == n) break;
135         work();
136     }
137     return 0;
138 }
View Code 


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<intint> 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, 0sizeof 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<intint>::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\n", sum);
93     }
94     return 0;
95 }
View Code 

 

posted @ 2013-09-18 20:20  masterhe  阅读(351)  评论(0编辑  收藏  举报