传送门:
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;
}