题目描述
给定一个含有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。
输出格式:
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
输入输出样例
输入样例#1:
5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3
输出样例#1:
3 6
说明
20%的数据中,m,n≤100;
40%的数据中,m,n≤1000;
100%的数据中,m,n≤10000。
来源:bzoj1901
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。
主席树+树状数组
主席树数组要往大的开
#include <algorithm> #include <ctype.h> #include <cstdio> #define N 10005 using std::sort; using std::unique; using std::lower_bound; inline int lowbit(int x) {return x&(-x);} inline void Read(int &x) { register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()); for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); } struct cmt { int l,r,Size; }tr[N*300]; struct cz { int l,r,k; }c[N*2]; int all,use[N*2],n,m,tot,size,rt[N],a[N],b[N],rank[N]; void update(int l,int r,int x,int &y,int t,int v) { y=++tot; tr[y].Size=tr[x].Size+v; if(l==r) return; tr[y].l=tr[x].l; tr[y].r=tr[x].r; int mid=(l+r)>>1; if(t<=mid) update(l,mid,tr[x].l,tr[y].l,t,v); else update(mid+1,r,tr[x].r,tr[y].r,t,v); } void add(int x,int p,int v) { for(;x<=n;x+=lowbit(x)) update(1,size,rt[x],rt[x],p,v); } inline int sum(int x) { int ans=0; for(;x;x-=lowbit(x)) ans+=tr[tr[use[x]].l].Size; return ans; } int query(int l,int r,int x,int y,int k) { if(l==r) return l; int tmp=sum(y)-sum(x-1); int mid=(l+r)>>1; if(tmp>=k) { for(int i=x-1;i;i-=lowbit(i)) use[i]=tr[use[i]].l; for(int i=y;i;i-=lowbit(i)) use[i]=tr[use[i]].l; return query(l,mid,x,y,k); } else { for(int i=x-1;i;i-=lowbit(i)) use[i]=tr[use[i]].r; for(int i=y;i;i-=lowbit(i)) use[i]=tr[use[i]].r; k-=tmp; return query(mid+1,r,x,y,k); } } inline int Rank(int x) {return lower_bound(b+1,b+1+all,x)-b;} int build(int l,int r) { int now=++tot; tr[now].Size=0; if(l==r) return now; int mid=(l+r)>>1; tr[now].l=build(l,mid); tr[now].r=build(mid+1,r); return now; } int main() { Read(n); Read(m); for(int i=1;i<=n;++i) Read(a[i]),b[i]=a[i]; char str[5]; all=n; for(int x,y,z,i=1;i<=m;++i) { scanf("%s",str); if(str[0]=='Q') { Read(x); Read(y); Read(z); c[i].l=x;c[i].r=y;c[i].k=z; } else { Read(x); Read(y); c[i]=(cz){0,x,y},b[++all]=y; } } for(int i=1;i<=n;++i) rt[i]=rt[0]; sort(b+1,b+1+all); size=unique(b+1,b+1+all)-b-1; rt[0]=build(1,size); for(int i=1;i<=n;++i) add(i,Rank(a[i]),1); for(int i=1;i<=m;++i) { if(c[i].l) { for(int k=c[i].l-1;k;k-=lowbit(k)) use[k]=rt[k]; for(int k=c[i].r;k;k-=lowbit(k)) use[k]=rt[k]; printf("%d ",b[query(1,size,c[i].l,c[i].r,c[i].k)]); } else { add(c[i].r,Rank(a[c[i].r]),-1); add(c[i].r,Rank(c[i].k),1); a[c[i].r]=c[i].k; } } return 0; }