传送门:
http://www.lydsy.com/JudgeOnline/problem.php?id=3196
刷了一上午……线段树套平衡树,rank支持区间加法,kth不支持,所以算kth就二分rank好了
Code:
#include<cstdio> #include<climits> #include<iostream> #include<algorithm> #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define L (i<<1) #define R (i<<1|1) const int maxn=50010; const int INF=INT_MAX; using namespace std; int a[50001]; int rnd(){ static int KEY=12345678; return KEY+=KEY<<2|1; } int n,m; int Left,Right,Find; struct Treap{ struct node{ int val;int key,size,s; node *c[2]; node(int _val,node *C){ val=_val;key=rand(); size=1;s=1; c[0]=c[1]=C; } void rz(){ size=c[0]->size+c[1]->size+s; } }; node *root,*Null; Treap(){ Null=new node(0,0); Null->size=0;Null->key=INF;Null->val=0; Null->c[0]=Null->c[1]=Null; root=Null; } void rot(node *&t,bool d){ node *p=t->c[d]; t->c[d]=p->c[!d]; p->c[!d]=t; t->rz();p->rz(); t=p; } void _insert(node *&t,int x){ if(t==Null){ t=new node(x,Null); return ; } if(t->val==x){ t->s++; t->size++; return; } bool d=x>t->val; _insert(t->c[d],x); if(t->c[d]->key<t->key) rot(t,d); else t->rz(); } void _Delete(node *&t,int x){ if(t==Null)return; if(t->val==x){ if(t->s>1){ t->s--; t->size--; return; } bool d=t->c[1]->key<t->c[0]->key; if(t->c[d]==Null){ delete t; t=Null; return ; } rot(t,d); _Delete(t->c[!d],x); }else{ bool d=x>t->val; _Delete(t->c[d],x); } t->rz(); } int _kth(node *&t,int x){ int r=t->c[0]->size; if(t==Null)return 0; else if(x<=r)return _kth(t->c[0],x); else if(x>r+t->s)return _kth(t->c[1],x-r-t->s); else return t->val; } int _rank(node *&t,int x){ int r=t->c[0]->size; if(t==Null)return 0; else if(x==t->val){Find=1;return r;} else if(x>t->val){Right++;return r+t->s+_rank(t->c[1],x);} else{Left++;return _rank(t->c[0],x);} } void _deb(node *&t){ printf("val:%d L:%d R:%d\n",t->val,t->c[0]->val,t->c[1]->val); //printf("key:%d L:%d R:%d\n",t->key,t->c[0]->key,t->c[1]->key); printf("size:%d L:%d R:%d\n",t->size,t->c[0]->size,t->c[1]->size); if(t->c[0]!=Null)_deb(t->c[0]); if(t->c[1]!=Null)_deb(t->c[1]); } void deb(){_deb(root);puts("");} void insert(int x){_insert(root,x);} void del(int x){_Delete(root,x);} int kth(int x){return _kth(root,x);} int rank(int x){return _rank(root,x);} int size(){return root->size;} int _prev(node *&t,int x){ if(t==Null)return INT_MIN; if(x<=t->val)return _prev(t->c[0],x); return max(t->val,_prev(t->c[1],x)); } int _next(node *&t,int x){ if(t==Null)return INT_MAX; if(x>=t->val)return _next(t->c[1],x); return min(t->val,_next(t->c[0],x)); } int prev(int x){ return _prev(root,x); } int next(int x){ return _next(root,x); } }; struct seg_tree{ Treap t[maxn<<2]; void build(int i,int l,int r){ if(l>r)return; for(int o=l;o<=r;o++) t[i].insert(a[o]); if(l==r)return; int mid=l+r>>1; build(lson); build(rson); } void change(int i,int l,int r,int pos,int val){ if(l>r)return; t[i].del(a[pos]); //a[pos]=val; t[i].insert(val); if(l==r){ a[pos]=val; return; } int mid=l+r>>1; if(pos<=mid)change(lson,pos,val); else change(rson,pos,val); } int rank(int i,int l,int r,int l0,int r0,int k){ if(l>r)return 0; int ans=0; if(l0<=l&&r0>=r) return t[i].rank(k); int mid=l+r>>1; if(l0<=mid)ans+=rank(lson,l0,r0,k); if(r0>mid) ans+=rank(rson,l0,r0,k); return ans; } int prev(int i,int l,int r,int l0,int r0,int k){ if(l>r)return 0; int ans=INT_MIN; if(l0<=l&&r0>=r) return t[i].prev(k); int mid=l+r>>1; if(l0<=mid)ans=max(ans,prev(lson,l0,r0,k)); if(r0>mid) ans=max(ans,prev(rson,l0,r0,k)); return ans; } int next(int i,int l,int r,int l0,int r0,int k){ if(l>r)return 0; int ans=INT_MAX; if(l0<=l&&r0>=r) return t[i].next(k); int mid=l+r>>1; if(l0<=mid)ans=min(ans,next(lson,l0,r0,k)); if(r0>mid) ans=min(ans,next(rson,l0,r0,k)); return ans; } }T; void Change(int pos,int k){ T.change(1,1,n,pos,k); } int Rank(int l,int r,int k){ Left=Right=Find=0; int res=T.rank(1,1,n,l,r,k); if(Find)return res+1; if(Left==0)return res+1; if(Right==0)return res; return res+1; } int kth(int l0,int r0,int k){ int l=0,r=int(1e8)+10; while(l<r){ int mid=l+r>>1; if(Rank(l0,r0,mid)<=k) l=mid+1; else r=mid; } return l-1; } int prev(int l,int r,int k){ return T.prev(1,1,n,l,r,k); } int next(int l,int r,int k){ return T.next(1,1,n,l,r,k); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); // Change(i,a[i]); } T.build(1,1,n); int opt,l,r,k,pos; while(m--){ scanf("%d",&opt); switch(opt){ case 1:{ scanf("%d%d%d",&l,&r,&k); printf("%d\n",Rank(l,r,k)); break; } case 2:{ scanf("%d%d%d",&l,&r,&k); printf("%d\n",kth(l,r,k)); break; } case 3:{ scanf("%d%d",&pos,&k); Change(pos,k); break; } case 4:{ scanf("%d%d%d",&l,&r,&k); printf("%d\n",prev(l,r,k)); break; } case 5:{ scanf("%d%d%d",&l,&r,&k); printf("%d\n",next(l,r,k)); break; } } } return 0; }