1901: Zju2112 Dynamic Rankings
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
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 ",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 }