传送门
(update at 10.31)
我的第一次调出样例:
我就很无语了,居然会TLE
然后hzy dalao就告诉我:“我们那个板子一直都是错的!”
然后就告诉了我splay的正确姿势,然后。。。
我就问他:“这难道不是你的板子吗?”
hzy:“你写的丑。”
我:“。。。”
然后我就愉快地去大(yang)牛(qi)分站交了一发,果断AC了这题。
其实我原来用的那个splay真的有问题,常数太大,每次都要splay好几次,查前驱后继还要插入&删除,所以常数大概大了3倍左右,所以会TLE。
这个splay还是不错的。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#define ll long long
using namespace std;
inline int read(){
int x=0;char ch=' ';int f=1;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
const int N=5e4+5;
const int inf=2147483647;
int n,m,sz;
int a[N],key[N*100],cnt[N*100],size[N*100],ch[N*100][2],f[N*100];
struct Splay{
int root;
inline bool get(int x){return ch[f[x]][1]==x;}
inline void clear(int x){key[x]=cnt[x]=size[x]=f[x]=ch[x][0]=ch[x][1]=0;}
inline void update(int x){size[x]=cnt[x]+size[ch[x][0]]+size[ch[x][1]];}
inline void rotate(int x){
int y=f[x],z=f[y],w=get(x),w2=get(y);
ch[y][w]=ch[x][w^1];f[ch[y][w]]=y;
ch[x][w^1]=y;f[y]=x;
f[x]=z;if(z)ch[z][w2]=x;
update(y);update(x);
}
inline void splay(int x){
for(int fa=0;(fa=f[x]);rotate(x))
if(f[fa])
rotate((get(x)==get(fa))?fa:x);
root=x;
}
inline void insert(int x){
if(!root){key[++sz]=x;cnt[sz]=size[sz]=1;root=sz;return;}
int now=root,fa;
while(1){
if(x==key[now]){cnt[now]++;update(now);splay(now);return;}
fa=now;
now=ch[now][x>key[now]];
if(!now){
ch[fa][x>key[fa]]=++sz;
key[sz]=x;cnt[sz]=size[sz]=1;f[sz]=fa;
update(fa);splay(sz);return;
}
}
}
inline int find(int x){
int now=root,ans=0;
while(1){
if(ch[now][0]&&x<key[now]){
now=ch[now][0];
}
else{
ans+=size[ch[now][0]];
if(x==key[now]){splay(now);return ans;}
ans+=cnt[now];now=ch[now][1];
}
}
}
inline int find2(int x){
int now=root,ans=0;
while(1){
if(ch[now][0]&&x<key[now]){
now=ch[now][0];
}
else{
ans+=size[ch[now][0]];
if(x==key[now]){splay(now);return ans+cnt[now];}
ans+=cnt[now];now=ch[now][1];
}
}
}
inline int pre(){
int now=ch[root][0];
while(ch[now][1])now=ch[now][1];
return now;
}
inline int next(){
int now=ch[root][1];
while(ch[now][0])now=ch[now][0];
return now;
}
inline void del(int x){
find(x);
if(cnt[root]>1){cnt[root]--;update(root);return;}
int leftbig=pre(),oldroot=root;
splay(leftbig);
ch[root][1]=ch[oldroot][1];f[ch[root][1]]=root;
clear(oldroot);update(root);
}
inline void print(int now){
if(ch[now][0])print(ch[now][0]);
cout<<key[now]<<' ';
if(ch[now][1])print(ch[now][1]);
}
}t[N<<2];
int L,R,x,pos,k,ans;
inline void build(int rt,int l,int r){
t[rt].root=0;
t[rt].insert(inf);t[rt].insert(-inf);
for(int i=l;i<=r;i++)t[rt].insert(a[i]);
if(l==r)return;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
inline void update(int rt,int l,int r){
t[rt].del(a[pos]);t[rt].insert(x);
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)update(rt<<1,l,mid);
else update(rt<<1|1,mid+1,r);
}
inline void find(int rt,int l,int r){
if(L<=l&&r<=R){t[rt].insert(x);ans+=t[rt].find(x)-1;t[rt].del(x);return;}
int mid=(l+r)>>1;
if(L<=mid)find(rt<<1,l,mid);
if(mid+1<=R)find(rt<<1|1,mid+1,r);
}
inline void find2(int rt,int l,int r){
if(L<=l&&r<=R){t[rt].insert(x);ans+=t[rt].find2(x)-2;t[rt].del(x);return;}
int mid=(l+r)>>1;
if(L<=mid)find2(rt<<1,l,mid);
if(mid+1<=R)find2(rt<<1|1,mid+1,r);
}
inline int kth(){
int l=0,r=1e8;
while(l<r){
x=(l+r)>>1;ans=0;find2(1,1,n);
if(ans+1<=k)l=x+1;
else r=x;
}
return r;
}
inline void pre(int rt,int l,int r){
if(L<=l&&r<=R){t[rt].insert(x);ans=max(ans,key[t[rt].pre()]);t[rt].del(x);return;}
int mid=(l+r)>>1;
if(L<=mid)pre(rt<<1,l,mid);
if(mid+1<=R)pre(rt<<1|1,mid+1,r);
}
inline void next(int rt,int l,int r){
if(L<=l&&r<=R){t[rt].insert(x);ans=min(ans,key[t[rt].next()]);t[rt].del(x);return;}
int mid=(l+r)>>1;
if(L<=mid)next(rt<<1,l,mid);
if(mid+1<=R)next(rt<<1|1,mid+1,r);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++)a[i]=read();
build(1,1,n);
while(m--){
int opt=read();
switch(opt){
case 1:L=read();R=read();x=read();ans=0;find(1,1,n);printf("%d\n",ans+1);break;
case 2:L=read();R=read();k=read();printf("%d\n",kth());break;
case 3:pos=read();x=read();update(1,1,n);a[pos]=x;break;
case 4:L=read();R=read();x=read();ans=-inf;pre(1,1,n);printf("%d\n",ans);break;
case 5:L=read();R=read();x=read();ans=inf;next(1,1,n);printf("%d\n",ans);break;
}
}
return 0;
}