bzoj1901

来源:互联网 发布:手机淘宝店铺装修教程 编辑:程序博客网 时间:2024/04/28 21:54

1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 6640  Solved: 2762
[Submit][Status][Discuss]

Description

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

Input

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

Output

 

Sample Input

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

Sample Output

3
6

HINT

 

20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

 

Source

 

 题解:区间第k大,加修改操作,就是动态主席树,用主席树套树状数组写,就慢慢地A了。
  1 #include<iostream>  2 #include<cstring>  3 #include<cstdio>  4 #include<cmath>  5 #include<algorithm>  6 #define maxn 200001  7 #define maxnode 2200001  8 using namespace std;  9 int list[maxn],h[maxn]; 10 int rt[maxnode],lt[maxnode],root[maxnode],sum[maxnode]; 11 int L[maxn],R[maxn]; 12 int ed,st,tot,size,n,node,m; 13 char ch; 14 struct date{int l,r,val,k; 15 }a[maxn]; 16 int read() 17 { 18     int x=0; char ch; bool bo=0; 19     while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') bo=1; 20     while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9'); 21     if (bo==1) return -x; return x; 22 } 23 int lowbit(int k) 24 { 25     return (k&(-k)); 26 } 27 void ins(int x,int &y,int l,int r,int val ,int kk) 28 { 29     y=++size; 30     sum[y]=sum[x]+kk; int mid=(l+r)>>1; rt[y]=rt[x]; lt[y]=lt[x]; 31     if (l==r) return ; 32     if (val<=mid) ins(lt[x],lt[y],l,mid,val,kk); 33     else ins(rt[x],rt[y],mid+1,r,val,kk); 34 } 35 void build() 36 { 37     for (int i=1; i<=n; i++) 38         for (int j=i; j<=n; j+=lowbit(j))  39         ins(root[j],root[j],1,tot,h[i],1); 40 } 41 int query(int l,int r,int k) 42 { 43     if (l==r) return l; 44     int mid=(l+r)>>1; int suml=0,sumr=0; 45     for (int i=1; i<=st; i++) suml+=sum[lt[L[i]]]; 46     for (int i=1; i<=ed; i++) sumr+=sum[lt[R[i]]]; 47     if (sumr-suml>=k) 48     { 49         for (int i=1; i<=st; i++) L[i]=lt[L[i]]; 50         for (int i=1; i<=ed; i++) R[i]=lt[R[i]]; 51         return query(l,mid,k);  52     } 53     else 54     { 55         for (int i=1; i<=st; i++) L[i]=rt[L[i]]; 56         for (int i=1; i<=ed; i++) R[i]=rt[R[i]]; 57         return query(mid+1,r,k-sumr+suml); 58     } 59 } 60 void solve() 61 { 62     node=n; 63     for (int i=1; i<=m; i++) 64     { 65         if (!a[i].k)  66         { 67             st=ed=0; 68             a[i].l--; 69             for (int j=a[i].l; j>0; j-=lowbit(j)) L[++st]=root[j]; 70             for (int j=a[i].r; j>0; j-=lowbit(j)) R[++ed]=root[j]; 71             printf("%d\n",list[query(1,tot,a[i].val)]);  72         } 73         else 74         { 75             ++node;  76             int t=h[a[i].l]; 77             for (int j=a[i].l; j<=n; j+=lowbit(j)) ins(root[j],root[j],1,tot,t,-1); 78             h[a[i].l]=t=h[node]; 79             for (int j=a[i].l; j<=n; j+=lowbit(j)) ins(root[j],root[j],1,tot,t,1); 80              81         } 82     } 83 } 84 void clear() 85 { 86     tot=size=0; 87     memset(root,0,sizeof(0)); 88     memset(rt,0,sizeof(0)); 89     memset(lt,0,sizeof(0)); 90     memset(sum,0,sizeof(0)); 91 } 92 int main() 93 { 94     //freopen("dynrank1.in","r",stdin); 95         clear(); 96         n=read(); m=read(); 97         for (int i=1; i<=n; i++) list[i]=h[i]=read(); 98         tot=n; 99         for (int i=1; i<=m; i++)100         {101             scanf(" %c",&ch);102             a[i].l=read(); a[i].r=read();103             if (ch=='Q') a[i].val=read();104             else a[i].k=1,h[++tot]=list[tot]=a[i].r;105         } 106         sort(list+1,list+tot+1);107         for (int i=1; i<=tot; i++) h[i]=lower_bound(list+1,list+1+tot,h[i])-list;108         build();109         solve();110     return 0;111 }
View Code

 

 
0 0