#106. 二逼平衡树
内存限制:512 MiB时间限制:4000 ms标准输入输出
题目类型:传统评测方式:文本比较
这是一道模板题。
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
- 查询 x 在区间内的排名;
- 查询区间内排名为 k 的值;
- 修改某一位置上的数值;
- 查询 x 在区间内的前趋(前趋定义为小于 x,且最大的数);
- 查询 x 在区间内的后继(后继定义为大于 x ,且最小的数)。
输入格式
第一行两个数 n,m,表示长度为 n 的有序序列和 m 个操作。
第二行有 n个数,表示有序序列。
下面有 m行,每行第一个数表示操作类型:
- 之后有三个数 l,r,x表示查询 x 在区间 [l,r]的排名;
- 之后有三个数 l,r,k 表示查询区间 [l,r] 内排名为 k 的数;
- 之后有两个数 pos,x表示将 pos位置的数修改为 x;
- 之后有三个数 l,r,x 表示查询区间 [l,r]内 x的前趋;
- 之后有三个数 l,r,x 表示查询区间 [l,r] 内 x的后继.
输出格式
对于操作 1,2,4,5各输出一行,表示查询结果。
样例
样例输入
9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
样例输出
2
4
3
4
9
数据范围与提示
1≤n,m≤5e4 −1e8≤k,x≤1e8
#include <bits/stdc++.h>
#define pt ch[ch[root][1]][0]
const int MAXN=1e5+10;
const int inf=1e8+10;
using namespace std;
int n;
int ch[MAXN<<7][2],size[MAXN<<7],pre[MAXN<<7],key[MAXN<<7],cnt2=0,psize;
int rt[MAXN],a[MAXN];
vector<int>vec;
void Treavel(int x)
{
if(x)
{
Treavel(ch[x][0]);
printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
Treavel(ch[x][1]);
}
}
void debug(int rp)
{
printf("root:%d\n",rp);
Treavel(rp);
}
typedef struct node{
int root,maxx;
void newnode(int &x,int fa,int vul){
x=++cnt2;ch[x][0]=ch[x][1]=0;pre[x]=fa;key[x]=vul;
size[x]=1;
}
void inte(){
root=0;
newnode(root,0,-inf);
newnode(ch[root][1],root,inf);
}
void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
void rotate(int x,int kind){
int y=pre[x];
ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
up(y);
}
void splay(int x,int goal){
while(pre[x]!=goal){
if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
else{
int y=pre[x];int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
else rotate(y,kind),rotate(x,kind);
}
}
if(goal==0) root=x;
up(x);
}
void insert(int &x,int vul,int fa){
if(!x){newnode(x,fa,vul);return ;}
if(key[x]>vul) insert(ch[x][0],vul,x);
else insert(ch[x][1],vul,x);
up(x);
}
int find1(int x,int vul){
if(key[x]==vul) return x;
else if(key[x]<vul) return find1(ch[x][1],vul);
else return find1(ch[x][0],vul);
}
int find2(int x,int siz){
if(siz==size[ch[x][0]]+1) return x;
else if(siz<=size[ch[x][0]]) return find2(ch[x][0],siz);
else return find2(ch[x][1],siz-size[ch[x][0]]-1);
}
void erase(int vul){
splay(find1(root,vul),0);
int t=size[ch[root][0]]+1;
splay(find2(root,t-1),0);
splay(find2(root,t+1),root);
pre[ch[ch[root][1]][0]]=0;ch[ch[root][1]][0]=0;up(ch[root][1]);up(root);
}
void pre_vul(int x,int vul){
if(!x) return ;
if(key[x]>=vul) pre_vul(ch[x][0],vul);
else{
if(vul-key[x]<=vul-maxx) maxx=key[x],pre_vul(ch[x][1],vul);
else pre_vul(ch[x][1],vul);
}
}
void last_vul(int x,int vul){
if(!x) return ;
if(key[x]<=vul) last_vul(ch[x][1],vul);
else{
if(key[x]-vul<=maxx-vul) maxx=key[x],last_vul(ch[x][0],vul);
else last_vul(ch[x][0],vul);
}
}
}node;
typedef struct wjy{
int l,r,sum;
}wjy;
wjy dd[MAXN<<7];int cnt1=0;
typedef struct List{
node T;
}List;
List d[MAXN<<2];
void built(int &x,int y,int l,int r,int vul,int flag){
x=++cnt1;dd[x]=dd[y];dd[x].sum+=flag;
if(l==r) return ;
int mid=(l+r)>>1;
if(vul<=mid) built(dd[x].l,dd[y].l,l,mid,vul,flag);
else built(dd[x].r,dd[y].r,mid+1,r,vul,flag);
}
int ans;
vector<int>vv1;
vector<int>vv2;
int get_id(int x){return x&(-x);}
void slove(int l,int r){
for(int i=l-1;i>0;i-=get_id(i)) vv2.push_back(rt[i]);
for(int i=r;i>0;i-=get_id(i)) vv1.push_back(rt[i]);
}
int querty1(int l,int r,int ql,int qr,int vul){
slove(ql,qr);
while(l<r){
int mid=(l+r)>>1;
if(mid<=vul){
l=mid+1;
for(int i=0;i<vv1.size();i++) ans+=dd[dd[vv1[i]].l].sum;
for(int i=0;i<vv2.size();i++) ans-=dd[dd[vv2[i]].l].sum;
for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].r;
for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].r;
}
else{
r=mid;
for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].l;
for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].l;
}
}
return ans;
}
int querty2(int l,int r,int ql,int qr,int k){
slove(ql,qr);
int t;
while(l<r){
int mid=(l+r)>>1;t=0;
for(int i=0;i<vv1.size();i++) t+=dd[dd[vv1[i]].l].sum;
for(int i=0;i<vv2.size();i++) t-=dd[dd[vv2[i]].l].sum;
if(t>=k){
r=mid;
for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].l;
for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].l;
}
else{
l=mid+1;k-=t;
for(int i=0;i<vv1.size();i++) vv1[i]=dd[vv1[i]].r;
for(int i=0;i<vv2.size();i++) vv2[i]=dd[vv2[i]].r;
}
}
return l;
}
void update1(int root,int l,int r,int vul,int t,int flag){
//cout<<l<<" "<<r<<endl;
//cout<<d[root].T.root<<endl;
if(flag) d[root].T.insert(d[root].T.root,vul,0);
else d[root].T.erase(vul);
//if(!flag) debug(d[root].T.root);
if(l==r) return ;
int mid=(l+r)>>1;
if(t<=mid) update1(root<<1,l,mid,vul,t,flag);
else update1(root<<1|1,mid+1,r,vul,t,flag);
}
int maxn;
void querty(int root,int l,int r,int ql,int qr,int x,int flag){
if(ql<=l&&r<=qr){
if(flag) d[root].T.maxx=-1*inf,d[root].T.pre_vul(d[root].T.root,x),maxn=max(maxn,d[root].T.maxx);
else d[root].T.maxx=inf,d[root].T.last_vul(d[root].T.root,x),maxn=min(maxn,d[root].T.maxx);
return ;
}
int mid=(l+r)>>1;
if(ql<=mid) querty(root<<1,l,mid,ql,qr,x,flag);
if(qr>mid) querty(root<<1|1,mid+1,r,ql,qr,x,flag);
}
void inte(){
for(int i=1;i<=(n<<2);i++) d[i].T.inte();
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j+=get_id(j)){
built(rt[j],rt[j],1,psize,a[i],1);
}
update1(1,1,n,a[i],i,1);
}
}
void update(int pos,int x,int y){
for(int j=pos;j<=n;j+=get_id(j)){
built(rt[j],rt[j],1,psize,x,-1);
built(rt[j],rt[j],1,psize,y,1);
}
update1(1,1,n,x,pos,0);
//cout<<"sb"<<endl;
update1(1,1,n,y,pos,1);
//cout<<"sb"<<endl;
}
int slove1(int l,int r,int x){
ans=0;
int ans1=querty1(1,psize,l,r,x-1);
vv1.clear();vv2.clear();
return ans1+1;
}
int slove2(int l,int r,int k){
ans=querty2(1,psize,l,r,k);
vv1.clear();vv2.clear();
return ans;
}
int slove3(int l,int r,int x){
maxn=-1*inf;querty(1,1,n,l,r,x,1);
return maxn;
}
int slove4(int l,int r,int x){
//cout<<l<<" "<<r<<endl;
maxn=inf;querty(1,1,n,l,r,x,0);
return maxn;
}
typedef struct P{
int op,l,r,x;
}P;
P p[MAXN];
int main(){
int m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),vec.push_back(a[i]);
for(int i=1;i<=m;i++){
scanf("%d",&p[i].op);
if(p[i].op==3) scanf("%d%d",&p[i].l,&p[i].x),vec.push_back(p[i].x);
else if(p[i].op==2) scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].x);
else scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].x),vec.push_back(p[i].x);
}
sort(vec.begin(),vec.end());
psize=unique(vec.begin(),vec.end())-vec.begin();
for(int i=1;i<=n;i++) a[i]=lower_bound(vec.begin(),vec.begin()+psize,a[i])-vec.begin()+1;
inte();
for(int i=1;i<=m;i++){
if(p[i].op==2) continue;
p[i].x=lower_bound(vec.begin(),vec.begin()+psize,p[i].x)-vec.begin()+1;
}
for(int i=1;i<=m;i++){
if(p[i].op==1) printf("%d\n",slove1(p[i].l,p[i].r,p[i].x));
else if(p[i].op==2) printf("%d\n",vec[slove2(p[i].l,p[i].r,p[i].x)-1]);
else if(p[i].op==3) update(p[i].l,a[p[i].l],p[i].x),a[p[i].l]=p[i].x;
else if(p[i].op==4) printf("%d\n",vec[slove3(p[i].l,p[i].r,p[i].x)-1]);
else printf("%d\n",vec[slove4(p[i].l,p[i].r,p[i].x)-1]);
}
return 0;
}