码迷,mamicode.com
首页 > 编程语言 > 详细

zoj2112 主席树动态第k大 (主席树&&树状数组)

时间:2015-10-10 20:02:24      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:

Dynamic Rankings

Time Limit: 10 Seconds      Memory Limit: 32768 KB

The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

Your task is to write a program for this computer, which

- Reads N numbers from the input (1 <= N <= 50,000)

- Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.


Input

The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.

The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

Q i j k or
C i t

It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

There‘re NO breakline between two continuous test cases.


Output

For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

There‘re NO breakline between two continuous test cases.


Sample Input

2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3


Sample Output

3
6
3
6

 

主席树太神了。

 

这题是动态第k大。

 

如果是不修改,直接主席树就可以了。

要修改要套如树状数组求和。

 

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2013-9-8 8:53:54
  4 File Name     :F:\2013ACM练习\专题学习\主席树\ZOJ2112.cpp
  5 ************************************************ */
  6 
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <vector>
 12 #include <queue>
 13 #include <set>
 14 #include <map>
 15 #include <string>
 16 #include <math.h>
 17 #include <stdlib.h>
 18 #include <time.h>
 19 using namespace std;
 20 
 21 const int MAXN = 60010;
 22 const int M = 2500010;
 23 int n,q,m,tot;
 24 int a[MAXN], t[MAXN];
 25 int T[MAXN], lson[M], rson[M],c[M];
 26 int S[MAXN];
 27 
 28 struct Query
 29 {
 30     int kind;
 31     int l,r,k;
 32 }query[10010];
 33 
 34 void Init_hash(int k)
 35 {
 36     sort(t,t+k);
 37     m = unique(t,t+k) - t;
 38 }
 39 int hash(int x)
 40 {
 41     return lower_bound(t,t+m,x)-t;
 42 }
 43 int build(int l,int r)
 44 {
 45     int root = tot++;
 46     c[root] = 0;
 47     if(l != r)
 48     {
 49         int mid = (l+r)/2;
 50         lson[root] = build(l,mid);
 51         rson[root] = build(mid+1,r);
 52     }
 53     return root;
 54 }
 55 
 56 int Insert(int root,int pos,int val)
 57 {
 58     int newroot = tot++, tmp = newroot;
 59     int l = 0, r = m-1;
 60     c[newroot] = c[root] + val;
 61     while(l < r)
 62     {
 63         int mid = (l+r)>>1;
 64         if(pos <= mid)
 65         {
 66             lson[newroot] = tot++; rson[newroot] = rson[root];
 67             newroot = lson[newroot]; root = lson[root];
 68             r = mid;
 69         }
 70         else
 71         {
 72             rson[newroot] = tot++; lson[newroot] = lson[root];
 73             newroot = rson[newroot]; root = rson[root];
 74             l = mid+1;
 75         }
 76         c[newroot] = c[root] + val;
 77     }
 78     return tmp;
 79 }
 80 
 81 int lowbit(int x)
 82 {
 83     return x&(-x);
 84 }
 85 int use[MAXN];
 86 void add(int x,int pos,int val)
 87 {
 88     while(x <= n)
 89     {
 90         S[x] = Insert(S[x],pos,val);
 91         x += lowbit(x);
 92     }
 93 }
 94 int sum(int x)
 95 {
 96     int ret = 0;
 97     while(x > 0)
 98     {
 99         ret += c[lson[use[x]]];
100         x -= lowbit(x);
101     }
102     return ret;
103 }
104 int Query(int left,int right,int k)
105 {
106     int left_root = T[left-1];
107     int right_root = T[right];
108     int l = 0, r = m-1;
109     for(int i = left-1;i;i -= lowbit(i)) use[i] = S[i];
110     for(int i = right;i ;i -= lowbit(i)) use[i] = S[i];
111     while(l < r)
112     {
113         int mid = (l+r)/2;
114         int tmp = sum(right) - sum(left-1) + c[lson[right_root]] - c[lson[left_root]];
115         if(tmp >= k)
116         {
117             r = mid;
118             for(int i = left-1; i ;i -= lowbit(i))
119                 use[i] = lson[use[i]];
120             for(int i = right; i; i -= lowbit(i))
121                 use[i] = lson[use[i]];
122             left_root = lson[left_root];
123             right_root = lson[right_root];
124         }
125         else
126         {
127             l = mid+1;
128             k -= tmp;
129             for(int i = left-1; i;i -= lowbit(i))
130                 use[i] = rson[use[i]];
131             for(int i = right;i ;i -= lowbit(i))
132                 use[i] = rson[use[i]];
133             left_root = rson[left_root];
134             right_root = rson[right_root];
135         }
136     }
137     return l;
138 }
139 void Modify(int x,int p,int d)
140 {
141     while(x <= n)
142     {
143         S[x] = Insert(S[x],p,d);
144         x += lowbit(x);
145     }
146 }
147 
148 int main()
149 {
150     //freopen("in.txt","r",stdin);
151     //freopen("out.txt","w",stdout);
152     int Tcase;
153     scanf("%d",&Tcase);
154     while(Tcase--)
155     {
156         scanf("%d%d",&n,&q);
157         tot = 0;
158         m = 0;
159         for(int i = 1;i <= n;i++)
160         {
161             scanf("%d",&a[i]);
162             t[m++] = a[i];
163         }
164         char op[10];
165         for(int i = 0;i < q;i++)
166         {
167             scanf("%s",op);
168             if(op[0] == Q)
169             {
170                 query[i].kind = 0;
171                 scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);
172             }
173             else
174             {
175                 query[i].kind = 1;
176                 scanf("%d%d",&query[i].l,&query[i].r);
177                 t[m++] = query[i].r;
178             }
179         }
180         Init_hash(m);
181         T[0] = build(0,m-1);
182         for(int i = 1;i <= n;i++)
183             T[i] = Insert(T[i-1],hash(a[i]),1);
184         for(int i = 1;i <= n;i++)
185             S[i] = T[0];
186         for(int i = 0;i < q;i++)
187         {
188             if(query[i].kind == 0)
189                 printf("%d\n",t[Query(query[i].l,query[i].r,query[i].k)]);
190             else
191             {
192                 Modify(query[i].l,hash(a[query[i].l]),-1);
193                 Modify(query[i].l,hash(query[i].r),1);
194                 a[query[i].l] = query[i].r;
195             }
196         }
197     }
198     return 0;
199 }

 

zoj2112 主席树动态第k大 (主席树&&树状数组)

标签:

原文地址:http://www.cnblogs.com/13224ACMer/p/4868057.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!