[luoguP2617] Dynamic Ranking(树状数组 套 主席树 + 离散化)

传送门

 

BZOJ上是权限题,洛谷赞啊。

求区间 K 大数很简单。

但是如果修改某个数的话,那么就得把这个数及后面所建的主席树都更新一遍 nlogn,显然不行。

所以可以在外面套一个树状数组来优化,树状数组的每一个节点都表示某个区间的主席树。

所以可以通过树状数组来求前缀和主席树。

具体实现看代码。

 

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 
 5 const int MAXN = 20005;
 6 int n, m, tot, cnt, size, t1, t2;
 7 int a[MAXN], b[MAXN], x[MAXN], y[MAXN], z[MAXN], q1[MAXN], q2[MAXN], root[MAXN], ls[MAXN * 100], rs[MAXN * 100], sum[MAXN * 100];
 8 char s[MAXN];
 9 
10 inline int read()
11 {
12     int x = 0;
13     char ch = getchar();
14     for(; !isdigit(ch); ch = getchar());
15     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
16     return x;
17 }
18 
19 inline void insert(int &now, int l, int r, int x, int v)
20 {
21     if(!now) now = ++cnt;
22     sum[now] += v;
23     if(l == r) return;
24     int mid = (l + r) >> 1;
25     if(x <= mid) insert(ls[now], l, mid, x, v);
26     else insert(rs[now], mid + 1, r, x, v);
27 }
28 
29 inline int query(int l, int r, int x)
30 {
31     if(l == r) return l;
32     int i, mid = (l + r) >> 1, ans = 0;
33     for(i = 1; i <= t1; i++) ans -= sum[ls[q1[i]]];
34     for(i = 1; i <= t2; i++) ans += sum[ls[q2[i]]];
35     if(x <= ans)
36     {
37         for(i = 1; i <= t1; i++) q1[i] = ls[q1[i]];
38         for(i = 1; i <= t2; i++) q2[i] = ls[q2[i]];
39         return query(l, mid, x);
40     }
41     else
42     {
43         for(i = 1; i <= t1; i++) q1[i] = rs[q1[i]];
44         for(i = 1; i <= t2; i++) q2[i] = rs[q2[i]];
45         return query(mid + 1, r, x - ans);
46     }
47 }
48 
49 int main()
50 {
51     int i, j, l, r;
52     n = read();
53     m = read();
54     for(i = 1; i <= n; i++) a[i] = read(), b[++tot] = a[i];
55     for(i = 1; i <= m; i++)
56     {
57         for(s[i] = getchar(); s[i] != 'Q' && s[i] != 'C'; s[i] = getchar());
58         if(s[i] == 'C') x[i] = read(), z[i] = read(), b[++tot] = z[i];
59         else x[i] = read(), y[i] = read(), z[i] = read();
60     }
61     
62     std::sort(b + 1, b + tot + 1);
63     size = std::unique(b + 1, b + tot + 1) - (b + 1);
64     for(i = 1; i <= n; i++) a[i] = std::lower_bound(b + 1, b + size + 1, a[i]) - b;
65     for(i = 1; i <= m; i++)
66         if(s[i] == 'C')
67             z[i] = std::lower_bound(b + 1, b + size + 1, z[i]) - b;
68     
69     for(i = 1; i <= n; i++)
70         for(j = i; j <= size; j += j & -j)
71             insert(root[j], 1, size, a[i], 1);
72     
73     for(i = 1; i <= m; i++)
74         if(s[i] == 'Q')
75         {
76             t1 = t2 = 0;
77             for(j = x[i] - 1; j; j -= j & -j) q1[++t1] = root[j];
78             for(j = y[i]; j; j -= j & -j) q2[++t2] = root[j];
79             printf("%d\n", b[query(1, size, z[i])]);
80         }
81         else 
82         {
83             for(j = x[i]; j <= size; j += j & -j) insert(root[j], 1, size, a[x[i]], -1);
84             a[x[i]] = z[i];
85             for(j = x[i]; j <= size; j += j & -j) insert(root[j], 1, size, z[i], 1);
86         }
87     return 0;
88 }
View Code

 

posted @ 2017-05-19 16:09  zht467  阅读(122)  评论(0编辑  收藏  举报