隐藏页面特效

1901: Zju2112 Dynamic Rankings

1901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 7339  Solved: 3055
[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

 

 
#include<cstdio> #include<algorithm> using namespace std; const int N=1e5+5; const int M=2200001; int n,m,cnt,top,a,b,X[N],A[N],B[N],v[N],num[N<<1],K[N],L[30],R[30]; int root[N],ls[M],rs[M],sum[M]; int lowbit(int x){ return x&-x; } void insert(int &k,int last,int l,int r,int x,int add){ k=++cnt; int mid=l+r>>1; ls[k]=ls[last]; rs[k]=rs[last]; sum[k]=sum[last]+add; if(l==r) return; if(x<=mid) insert(ls[k],ls[last],l,mid,x,add); else insert(rs[k],rs[last],mid+1,r,x,add); } int query(int l,int r,int k){ if(l==r) return l; int mid=l+r>>1; int suml=0,sumr=0; for(int i=1;i<=a;i++)suml+=sum[ls[L[i]]]; for(int i=1;i<=b;i++)sumr+=sum[ls[R[i]]]; if(sumr-suml>=k){ for(int i=1;i<=a;i++) L[i]=ls[L[i]]; for(int i=1;i<=b;i++) R[i]=ls[R[i]]; return query(l,mid,k); } else{ for(int i=1;i<=a;i++) L[i]=rs[L[i]]; for(int i=1;i<=b;i++) R[i]=rs[R[i]]; return query(mid+1,r,k-(sumr-suml)); } } int main(){ scanf("%d%d",&n,&m);top=n; for(int i=1;i<=n;i++) scanf("%d",&v[i]),num[i]=v[i]; char opt[6]; for(int i=1;i<=m;i++){ scanf("%s%d%d",opt,&A[i],&B[i]); if(opt[0]=='Q') scanf("%d",&X[i]),K[i]=1; else num[++top]=B[i]; } sort(num+1,num+top+1); int tot=unique(num+1,num+top+1)-num-1; for(int i=1;i<=n;i++){ int t=lower_bound(num+1,num+tot+1,v[i])-num; for(int j=i;j<=n;j+=lowbit(j)) insert(root[j],root[j],1,tot,t,1); } for(int i=1;i<=m;i++){ if(K[i]){ a=0,b=0;A[i]--; for(int j=A[i];j>=1;j-=lowbit(j)) L[++a]=root[j]; for(int j=B[i];j>=1;j-=lowbit(j)) R[++b]=root[j]; printf("%d\n",num[query(1,tot,X[i])]); } else{ int t=lower_bound(num+1,num+tot+1,v[A[i]])-num; for(int j=A[i];j<=n;j+=lowbit(j)) insert(root[j],root[j],1,tot,t,-1); v[A[i]]=B[i]; t=lower_bound(num+1,num+tot+1,v[A[i]])-num; for(int j=A[i];j<=n;j+=lowbit(j)) insert(root[j],root[j],1,tot,t,1); } } }

 

分块代码

 

#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; template <typename T> inline void read(T &x){ T f=1;char ch=getchar();x=0; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} x*=f; } inline char in(){ for(char ch=getchar();;ch=getchar()) if(ch>='A'&&ch<='Z') return ch; } const int N=1e5+5; int n,m,bsize,a[N],b[N],bl[N];char op; inline void init(int id){ sort(b+(id-1)*bsize+1,b+min(id*bsize,n)+1); } inline void change(int x,int y){ (*lower_bound(b+(bl[x]-1)*bsize+1,b+min(bl[x]*bsize,n)+1,a[x]))=y; sort(b+(bl[x]-1)*bsize+1,b+min(bl[x]*bsize,n)+1); a[x]=y; } int nownum; #define calc res+=a[i]<now,nownum+=a[i]==now; inline int count_num(int x,int y,int now){ int res=0;nownum=0; if(bl[x]==bl[y]){ for(int i=x;i<=y;i++) calc } else{ for(int i=x;i<=bl[x]*bsize;i++) calc for(int i=(bl[y]-1)*bsize+1;i<=y;i++) calc for(int i=bl[x]+1,p1,p2,l,r;i<bl[y];i++){ l=(i-1)*bsize+1; r=min(i*bsize,n); p1=lower_bound(b+l,b+r+1,now)-(b+l); p2=upper_bound(b+l,b+r+1,now)-(b+l); res+=p1; nownum+=p2-p1; } } return res; } int mx,mn; #define maxmin mx=max(mx,a[i]),mn=min(mn,a[i]); inline int range(int x,int y){ mx=-2e9;mn=2e9; if(bl[x]==bl[y]){ for(int i=x;i<=y;i++) maxmin } else{ for(int i=x;i<=bl[x]*bsize;i++) maxmin for(int i=(bl[y]-1)*bsize+1;i<=y;i++) maxmin for(int i=bl[x]+1,p,l,r;i<bl[y];i++){ l=(i-1)*bsize+1; r=min(i*bsize,n); mx=max(mx,b[r]); mn=min(mn,b[l]); } } } inline int query(int x,int y,int k){ range(x,y); int l=mn,r=mx,mid,less; while(l<=r){ mid=l+r>>1; less=count_num(x,y,mid); if(less+1<=k&&less+nownum>=k) return mid; if(less>=k) r=mid-1; else l=mid+1; } return l; } int main(){ read(n);read(m);bsize=sqrt(n+0.5); for(int i=1;i<=n;i++) read(a[i]),b[i]=a[i]; for(int i=1;i<=n;i++) bl[i]=(i-1)/bsize+1; for(int i=1;i<=bl[n];i++) init(i); for(int i=1,x,y,z;i<=m;i++){ op=in();read(x),read(y); if(op=='C') change(x,y); if(op=='Q') read(z),printf("%d\n",query(x,y,z)); } return 0; }

 

 

 


__EOF__

本文作者shenben
本文链接https://www.cnblogs.com/shenben/p/6281390.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   神犇(shenben)  阅读(209)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示