Dynamic Rankings(动态区间求第K小模板题:树套树(第二份模板效率更高,见下面截图))

来源:互联网 发布:暴雪降至 知乎 编辑:程序博客网 时间:2024/05/16 14:39


Link:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1112


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 queryingthe 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


(adviser)
Site: http://zhuzeyuan.hp.infoseek.co.jp/index.files/our_contest_20040619.htm


Author: XIN, Tao
Source: Online Contest of Christopher's Adventure


参考博客:http://blog.csdn.net/d891320478/article/details/8648171

AC code:

#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define N 60010#define M 60010#define INF 1000000000char ctrl[M][3];int cnt,n,m;int P[M],Q[M],a[N],b[N],K[M];struct treap{   int key,wei,cnt,size,ch[2];}T[N * 15];int tree[N << 1],nodecnt,root;void init(){   T[0].size = 0;   T[0].wei = -INF;   nodecnt = root = 0;}int ID(int l,int r){return l + r | l != r;}void update(int x){   T[x].size = T[T[x].ch[0]].size + T[T[x].ch[1]].size + T[x].cnt;}void rotate(int &x,int t){   int y = T[x].ch[t];   T[x].ch[t] = T[y].ch[!t];   T[y].ch[!t] = x;   update(x);   update(y);   x = y;}void insert(int &x,int t){   if (!x){       x = ++ nodecnt;       T[x].key = t;       T[x].wei = rand();       T[x].cnt = 1;       T[x].ch[0] = T[x].ch[1] = 0;   }else if (T[x].key == t) T[x].cnt ++;   else{       int k = T[x].key < t;       insert(T[x].ch[k],t);       if (T[x].wei < T[T[x].ch[k]].wei) rotate(x,k);   }   update(x);}void erase(int &x,int t){   if (T[x].key == t){       if (T[x].cnt == 1){           if (!T[x].ch[0] && !T[x].ch[1]) {               x = 0;return;           }           rotate(x,T[T[x].ch[0]].wei < T[T[x].ch[1]].wei);           erase(x,t);       }else T[x].cnt --;   }else erase(T[x].ch[T[x].key < t],t);   update(x);}int select(int x,int t){   if (!x) return 0;   if (T[x].key > t) return select(T[x].ch[0],t);   return T[x].cnt + T[T[x].ch[0]].size + select(T[x].ch[1],t);}void treeins(int l,int r,int i,int x){   insert(tree[ID(l,r)],x);   if (l == r) return;   int m = l + r >> 1;   if (i <= m) treeins(l,m,i,x);   else treeins(m + 1,r,i,x);}void treedel(int l,int r,int i,int x){   erase(tree[ID(l,r)],x);   if (l == r) return;   int m = l + r >> 1;   if (i <= m) treedel(l,m,i,x);   else treedel(m + 1,r,i,x);}int query(int l,int r,int x,int y,int t){   if (l == r) return l;   int m = l + r >> 1;   int ans = select(tree[ID(l,m)],y) - select(tree[ID(l,m)],x);   if (ans >= t) return query(l,m,x,y,t);   return query(m + 1,r,x,y,t - ans);}int main(){   //freopen("in.txt","r",stdin);   int Times;   int cas;   scanf("%d",&cas);   while(cas--){      scanf("%d%d",&n,&m);       memset(tree,0,sizeof tree);       init();       cnt = 0;       for (int i = 1;i <= n;i ++) scanf("%d",&a[i]),b[++ cnt] = a[i];       for (int i = 1;i <= m;i ++){           scanf("%s%d%d",ctrl[i],&P[i],&Q[i]);           if (ctrl[i][0] == 'Q') scanf("%d",&K[i]);           else b[++ cnt] = Q[i];       }       sort(b + 1,b + 1 + cnt);       cnt = unique(b + 1,b + 1 + cnt) - b - 1;       for (int i = 1;i <= n;i ++) {           a[i] = lower_bound(b + 1,b + 1 + cnt,a[i]) - b;           treeins(1,cnt,a[i],i);       }       for (int i = 1;i <= m;i ++){           if (ctrl[i][0] == 'Q'){               int id = query(1,cnt,P[i] - 1,Q[i],K[i]);               printf("%d\n",b[id]);           }else{               treedel(1,cnt,a[P[i]],P[i]);               a[P[i]] = lower_bound(b + 1,b + 1 + cnt,Q[i]) - b;               treeins(1,cnt,a[P[i]],P[i]);           }       }   }   return 0;}

附上别人较简化的代码版本(通过加二分分治优化):

该代码来自博客:http://blog.csdn.net/firenet1/article/details/47858071

AC code:

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<vector>using namespace std;#define maxn 300007int tree[maxn];void add(int p,int n){    for(;p<maxn;p+=p&(-p))        tree[p]+=n;}int query(int p){    int ans = 0;    for(;p>0;p-=p&(-p))        ans += tree[p];    return ans;}struct Node{    int l,r,k,ty,ans;};Node p[maxn];int id1[maxn],id2[maxn];void CDQ(int L,int R,int low,int high){    if(R < L) return ;    if(low == high ){        for(;L<=R;L++){            p[id1[L]].ans = low;        }        return ;    }    int mid = (low+high)/2,l=L,r=R,k,u;    for(int i = L;i <= R; i++){        u = id1[i];       if(p[u].ty == 2){            k = query(p[u].r) - query(p[u].l-1);            if(k >= p[u].k) id2[l++] = u;            else {                p[u].k -= k;                id2[r--] = u;            }        }        else if(p[u].k <= mid){            add(p[u].l,p[u].ty);            id2[l++] = u;        }        else id2[r--] =  u;    }    for(int i = L; i <= R; i++){        u = id1[i];        if(p[u].ty != 2 && p[u].k <= mid) add(p[u].l,-p[u].ty);    }    for(k=L;k<l;k++)        id1[k] = id2[k];    for(r=R;k<=R;k++)        id1[k] = id2[r--];    CDQ(L,l-1,low,mid);    CDQ(l,R,mid+1,high);}int num[maxn];int main(){    int n,q,t,cnt;    memset(tree,0,sizeof(tree));    int cas;    scanf("%d",&cas);    while(cas--){    scanf("%d%d",&n,&q);        for(cnt=0;cnt<n;cnt++){            scanf("%d",&p[cnt].k);            p[cnt].ty = 1;            p[cnt].l = cnt+1;            num[cnt+1] = p[cnt].k;        }        //scanf("%d",&q);        int ty,l,v;        char ch;        for(int i = 0;i < q; i++,cnt++){            scanf("\n%ch",&ch);            if(ch=='Q')            {            p[cnt].ty=2;}else{p[cnt].ty=1;}            if(p[cnt].ty == 1){                scanf("%d%d",&l,&v);                p[cnt].ty = -1;                p[cnt].k = num[l];                p[cnt].l = l;                cnt++;                num[l] = v;                p[cnt].ty = 1;                p[cnt].k = v;                p[cnt].l = l;            }            else {                scanf("%d%d%d",&p[cnt].l,&p[cnt].r,&p[cnt].k);            }        }        for(int i = 0;i < cnt; i++)            id1[i] = i;        CDQ(0,cnt-1,0,1000000000);        for(int i = 0;i < cnt; i++){            if(p[i].ty == 2) printf("%d\n",p[i].ans);        }    }    return 0;}


两份代码比较,显然第二份(后提交的那份)更优:

Run IDSubmit TimeJudge StatusPro.IDExe.TimeExe.MemoryCode Len.LanguageAuthor146888612015-08-29 23:02:59Accepted54121918MS11248K2440 BG++落纸云烟146884572015-08-29 21:58:02Accepted54124414MS83288K3251 BG++落纸云烟


0 0
原创粉丝点击