ZZUOJ 10508 树状数组

链接:

http://acm.zzu.edu.cn:8000/problem.php?id=10508

题意:

给定一个序列,长度为N,每次询问为一组区间[Li,Ri],输出Li到Ri中出现恰好两次的不同数的个数.

题解:

先对a离散化一下,当然也可以不离散化,用map也行。离线做,按右端点排序,从1遍历到n,更新树状数组和ans

对于a数组,我们记录上一个和a[i]相等的位置last[i],更新树状数组不太好想,具体看代码

代码:

31 int n, m;
32 int a[MAXN];
33 int last[MAXN];
34 int pos[MAXN];
35 int T[MAXN];
36 int ans[MAXN];
37 
38 struct node {
39     int l, r, id;
40     bool operator< (const node &t) const {
41         if (r == t.r) return l < t.l;
42         return r < t.r;
43     }
44 }q[MAXN];
45 
46 void add(int i, int x) {
47     while (i <= n) T[i] += x, i += i&-i;
48 }
49 
50 int sum(int i) {
51     int s = 0;
52     while (i) s += T[i], i -= i&-i;
53     return s;
54 }
55 
56 int main() {
57     scanf("%d%d", &n, &m);
58     VI v;
59     rep(i, 1, n + 1) scanf("%d", a + i), v.pb(a[i]);
60     sort(all(v));
61     v.erase(unique(all(v)), v.end());
62     rep(i, 1, n + 1) a[i] = lower_bound(all(v), a[i]) - v.begin() + 1;
63     rep(i, 1, n + 1) last[i] = pos[a[i]], pos[a[i]] = i;
64     rep(i, 0, m) {
65         scanf("%d%d", &q[i].l, &q[i].r);
66         q[i].id = i;
67     }
68     sort(q, q + m);
69     int index = 0;
70     rep(i, 1, n + 1) {
71         int p = last[i];
72         if (p) {
73             add(p, 1);
74             p = last[p];
75             if (p) {
76                 add(p, -2);
77                 p = last[p];
78                 if (p) add(p, 1);
79             }
80         }
81         while (index < m && q[index].r == i) {
82             int x = sum(q[index].r) - sum(q[index].l - 1);
83             ans[q[index].id] = x;
84             index++;
85         }
86     }
87     rep(i, 0, m) printf("%d\n", ans[i]);
88     return 0;
89 }

 

posted @ 2017-09-09 20:16  Flowersea  阅读(137)  评论(0编辑  收藏  举报