COJ986 WZJ的数据结构(负十四)
WZJ的数据结构(负十四) |
难度级别:D; 运行时间限制:6000ms; 运行空间限制:262144KB; 代码长度限制:2000000B |
试题描述
|
请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,M次操作,操作分两种: 1.1 i j k 每次询问给你i,j,k三个参数,求Ai至Aj中第k小的数。 2.0 x v 每次操作给你x,v两个参数,将A[x]改成v。 |
输入
|
第一行为两个正整数N,M。
第二行为N个正整数Ai。 接下来M行为操作。 |
输出
|
对于每个询问输出答案(保证k合法)。
|
输入示例
|
6 8
1 3 2 2 5 3 1 1 3 2 1 1 4 2 1 1 4 3 1 1 4 4 0 4 3 1 1 4 3 0 2 5 1 1 4 4 |
输出示例
|
2
2 2 3 3 5 |
其他说明
|
1<=N,M,Ai,v<=100000
1<=i<=j<=N 1<=k<=j-i+1 1<=x<=N |
写一个二分+树状数组+Treap,挺爽的
#include<cstdio> #include<cctype> #include<queue> #include<ctime> #include<cstring> #include<algorithm> #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; const int maxnode=2000010; struct Node { Node* ch[2]; int r,s,v; void maintain() {s=ch[0]->s+ch[1]->s+1;} }nodes[maxnode],*null=&nodes[0]; queue<Node*> del; int n,A[maxn],ToT; Node* newnode(int v) { Node* o; if(!del.empty()) o=del.front(),del.pop(); else o=&nodes[++ToT]; o->ch[0]=o->ch[1]=null; o->s=1;o->v=v;o->r=rand(); return o; } void remove(Node* &o) { del.push(o);o=null; } void rotate(Node* &o,int d) { Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o; o->maintain();k->maintain();o=k; } void insert(Node* &o,int v) { if(o==null) o=newnode(v); else { int d=v>o->v;insert(o->ch[d],v); if(o->ch[d]->r>o->r) rotate(o,d^1); else o->maintain(); } } void remove(Node* &o,int v) { if(o->v==v) { Node* t=o; if(o->ch[0]==null) o=o->ch[1],remove(t); else if(o->ch[1]==null) o=o->ch[0],remove(t); else { int d=o->ch[0]->r>o->ch[1]->r; rotate(o,d);remove(o->ch[d],v); } } else remove(o->ch[v>o->v],v); if(o!=null) o->maintain(); } void print(Node* o) { if(o==null) return; print(o->ch[0]); printf("%d ",o->v); print(o->ch[1]); } int query(Node* &o,int v) { if(o==null) return 0; if(v<=o->v) return query(o->ch[0],v); return query(o->ch[1],v)+o->ch[0]->s+1; } Node* root[maxn]; void insert(int x,int v) {for(;x<=n;x+=x&-x) insert(root[x],v);} void update(int x,int v) {for(;x<=n;x+=x&-x) remove(root[x],v);} int query(int x,int v) {int ret=0;for(;x;x-=x&-x) ret+=query(root[x],v+1);return ret;} int main() { null->s=0;srand(time(0)); n=read();int m=read(); rep(1,n) root[i]=null; rep(1,n) insert(i,A[i]=read()); while(m--) { if(read()) { int l=read(),r=read(),k=read(); int L=1,R=100000,M; while(L<R) if(query(r,M=L+R>>1)-query(l-1,M=L+R>>1)>=k) R=M; else L=M+1; printf("%d\n",L); } else { int x=read();update(x,A[x]); insert(x,A[x]=read()); } } return 0; }
复习一下树状数组+可持久化线段树,写WA了一发真不爽
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; const int maxnode=20000010; int ls[maxnode],rs[maxnode],s[maxnode],ToT; int n,m,A[maxn],root[maxn],c[maxn]; void update(int& y,int x,int l,int r,int pos,int v) { s[y=++ToT]=s[x]+v;if(l==r) return; int mid=l+r>>1;ls[y]=ls[x];rs[y]=rs[x]; if(pos<=mid) update(ls[y],ls[x],l,mid,pos,v); else update(rs[y],rs[x],mid+1,r,pos,v); } void update(int x,int v) { for(int i=x;i<=n;i+=i&-i) update(c[i],c[i],1,100000,A[x],-1); for(int i=x;i<=n;i+=i&-i) update(c[i],c[i],1,100000,A[x]=v,1); } int lt[maxn],rt[maxn],ltot,rtot; void get(int x,int tp) { if(!tp) {lt[ltot=1]=root[x];for(;x;x-=x&-x) if(c[x]) lt[++ltot]=c[x];} else {rt[rtot=1]=root[x];for(;x;x-=x&-x) if(c[x]) rt[++rtot]=c[x];} } int main() { n=read();m=read(); rep(1,n) update(root[i],root[i-1],1,100000,A[i]=read(),1); while(m--) { if(!read()) { int x=read(),v=read(); update(x,v); } else { int ql=read(),qr=read(),k=read(); get(ql-1,0);get(qr,1);int l=1,r=100000; while(l<r) { int mid=l+r>>1,tot=0; rep(1,ltot) tot-=s[ls[lt[i]]]; rep(1,rtot) tot+=s[ls[rt[i]]]; if(tot>=k) { r=mid; rep(1,ltot) lt[i]=ls[lt[i]]; rep(1,rtot) rt[i]=ls[rt[i]]; } else { l=mid+1;k-=tot; rep(1,ltot) lt[i]=rs[lt[i]]; rep(1,rtot) rt[i]=rs[rt[i]]; } } printf("%d\n",l); } } return 0; }