题目描述:
描述?描述个屁!
就是让你写个数据结构,资瓷一堆恶心的操作.
题目分析:
如果没有区间限制,这就是道裸的不能再裸的Splay!
然而加入区间限制要求我们可持久化
什么BIT套Seg啊 主席树套BIT啊
Seg套Treap啊 还有分块大佬!
然后我就写了Seg套Splay
(刚开始想搞普通线段树套个权值来着,无奈不会搞前驱后继,如果会了在搞吧qwq
其实树套树并不难理解
这道题目的一维就是一颗Seg 用来维护 区间查询操作
而不同的是,Seg上不是维护着一个个信息,而是直接挂了一颗Splay
这颗Splay存有所有属于本Seg节点区间所有值
然后我们在Splay里来进行维护即可!
第一次打这么长的代码
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define il inline
const int maxm=4000010;
const int inf=2147483647;
int ans;
int rt[maxm],siz[maxm],cnt[maxm],ch[maxm][2],fa[maxm],data[maxm];
int sz,MX,n,q;
int a[maxm];
il void splayclear(int x)
{
siz[x]=cnt[x]=ch[x][0]=ch[x][1]=fa[x]=data[x]=0;
}
il void update(int x)
{
siz[x]=cnt[x];
if(ch[x][0]) siz[x]+=siz[ch[x][0]];
if(ch[x][1]) siz[x]+=siz[ch[x][1]];
}
il bool get(int x)
{
return ch[fa[x]][1]==x;
}
il void rotate(int x)
{
int fax=fa[x],ffa=fa[fax],which=get(x);
bool fx=get(fax);
ch[fax][which]=ch[x][which^1];
fa[ch[fax][which]]=fax;
ch[x][which^1]=fax;
fa[fax]=x;
fa[x]=ffa;
if(ffa)
ch[ffa][fx]=x;
update(fax),update(x);
}
inline void splay(int i,int x,int top)
{
for(int fax;(fax=fa[x])!=0;rotate(x))
if(fa[fax]!=0)
rotate(get(fax)==get(x)?fax:x);
rt[i]=x;
}
il void splayinsert(int i,int val)
{
if(!rt[i])
{
sz++;
fa[sz]=ch[sz][0]=ch[sz][1]=0;
data[sz]=val,cnt[sz]=1,siz[sz]=1;
rt[i]=sz;
return;
}
int now=rt[i],fax=0;
while(1)
{
if(data[now]==val)
{
cnt[now]++,update(now),update(fax),splay(i,now,0);
return;
}
fax=now;
now=ch[fax][data[now]<val];
if(!now)
{
sz++;
ch[sz][0]=ch[sz][1]=0;
data[sz]=val,cnt[sz]=1,siz[sz]=1;
fa[sz]=fax,ch[fax][data[fax]<val]=sz;
update(fax);
splay(i,sz,0);
return;
}
}
}
il int splayrank(int i,int val)
{
int x=rt[i],ret=0;
while (x)
{
if (data[x]==val) return ret+((ch[x][0])?siz[ch[x][0]]:0);
if (data[x]<val)
{
ret+=((ch[x][0])?siz[ch[x][0]]:0)+cnt[x];
x=ch[x][1];
} else x=ch[x][0];
}
return ret;
}
il int splayfind(int i,int val)
{
int x=rt[i];
while(x)
{
if(data[x]==val)
{
splay(i,x,0);
return x;
}
x=ch[x][val>data[x]];
}
}
il int splaypre(int i)
{
int x=ch[rt[i]][0];
while(ch[x][1]) x=ch[x][1];
return x;
}
il int splaynext(int i)
{
int x=ch[rt[i]][1];
while(ch[x][0]) x=ch[x][0];
return x;
}
il void splaydel(int i,int val)
{
int x=splayfind(i,val);
if(cnt[x]>1)
{
cnt[x]--,update(x);
return;
}
if(!ch[x][0]&&!ch[x][1])
{
splayclear(rt[i]);
rt[i]=0;
return;
}
if (!ch[x][0])
{
int y=ch[x][1];
rt[i]=y,fa[y]=0;
return;
}
if (!ch[x][1])
{
int y=ch[x][0];
rt[i]=y,fa[y]=0;
return;
}
int p=splaypre(i);
int oldrt=rt[i];
splay(i,p,0);
ch[rt[i]][1]=ch[oldrt][1];
fa[ch[oldrt][1]]=rt[i];
splayclear(oldrt);
update(rt[i]);
}
il int splaygetpre(int i,int val)
{
int ret=-inf;
int x=rt[i];
while(x)
{
if (data[x]<val)
{
if(ret<data[x]) ret=data[x];
x=ch[x][1];
} else x=ch[x][0];
}
return ret;
}
il int splaygetnext(int i, int v)
{
int ret=inf;
int x=rt[i];
while(x)
{
if (data[x]>v)
{
if(ret>data[x]) ret=data[x];
x=ch[x][0];
} else x=ch[x][1];
}
return ret;
}
il void seginsert(int o,int l,int r,int ind,int num)
{
splayinsert(o,num);
if(l>=r) return;
int mid=(l+r)>>1;
if(ind<=mid) seginsert((o<<1),l,mid,ind,num);
else seginsert((o<<1)|1,mid+1,r,ind,num);
}
il void segrank(int o,int l,int r,int ql,int qr,int num)
{
if(ql<=l&&r<=qr)
{
ans+=splayrank(o,num);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) segrank((o<<1),l,mid,ql,qr,num);
if(qr>mid) segrank((o<<1)|1,mid+1,r,ql,qr,num);
}
il void segchange(int o,int l,int r,int ind,int ynum,int cnum)
{
splaydel(o,ynum),splayinsert(o,cnum);
if(l>=r) return;
int mid=(l+r)>>1;
if(ind<=mid) segchange((o<<1),l,mid,ind,ynum,cnum);
else segchange((o<<1)|1,mid+1,r,ind,ynum,cnum);
}
il void segpre(int o,int l,int r,int ql,int qr,int num)
{
if(ql<=l&&r<=qr)
{
ans=std::max(ans,splaygetpre(o,num));
return;
}
int mid=(l+r)>>1;
if(ql<=mid) segpre((o<<1),l,mid,ql,qr,num);
if(qr>mid) segpre((o<<1)|1,mid+1,r,ql,qr,num);
}
il void segnext(int o,int l,int r,int ql,int qr,int num)
{
if(ql<=l&&r<=qr)
{
ans=std::min(ans,splaygetnext(o,num));
return;
}
int mid=(l+r)>>1;
if(ql<=mid) segnext((o<<1),l,mid,ql,qr,num);
if(qr>mid) segnext((o<<1)|1,mid+1,r,ql,qr,num);
}
il int getkth(int ql,int qr,int k)
{
int l=0,r=MX+1;
while(l<r)
{
int mid=(l+r)>>1;
ans=0;
segrank(1,1,n,ql,qr,mid);
if (ans<k) l=mid+1;
else r=mid;
}
return l-1;
}
int main()
{
//freopen("wc.in","r",stdin);
//freopen("he.out","w",stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
MX=std::max(MX,a[i]);
seginsert(1,1,n,i,a[i]);
}
for(int i=1,l,r,k,opt;i<=q;i++)
{
scanf("%d",&opt);
if(opt==3)
{
scanf("%d%d",&l,&k);
segchange(1,1,n,l,a[l],k);
a[l]=k;
}
else
{
scanf("%d%d%d",&l,&r,&k);
if(opt==1)
{
ans=0;
segrank(1,1,n,l,r,k);
printf("%d\n",ans+1);
}
if(opt==2)
printf("%d\n",getkth(l,r,k));
if(opt==4)
{
ans=-inf;
segpre(1,1,n,l,r,k);
printf("%d\n",ans);
}
if(opt==5)
{
ans=inf;
segnext(1,1,n,l,r,k);
printf("%d\n",ans);
}
}
}
return 0;
}