非选treap真是个好东西!
bzoj3224有个实现细节我看网上都是错的,即split的时候,可能有重复元素(也就是1 x了相同的x很多次),然后求kth的时候不能把那个点拆成两个(否则merge的时候正确性和代码复杂度和时间复杂度都不能保证……吧?)。还有就是非旋treap其实不需要像splay一样一开始插入一个inf和INF来减少特判。
bzoj 3224:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#define ull unsigned long long
#define gc getchar()
#define mp make_pair
#define fir first
#define sec second
#define N 100010
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
int x=0,s=1,ch;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
if(ch^'-') x=ch^'0';else s=-1;
while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
return s*x;
}
int ch[N][2],sz[N],cnt[N],val[N];ull key[N];
struct Rand{
ull x;Rand() { x=0; }
inline ull operator()() { return x*=998244353,x^=1000000007,x^=(x<<13)^(x>>5)^945632; }
}rnd;
struct Treap{
int rt,node_cnt;
Treap() { rt=node_cnt=0,insert(INT_MIN+10),insert(INT_MAX-10),cnt[1]=cnt[2]=sz[1]=sz[2]=0; }
inline int push_up(int x) { return sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x]; }
inline int setc(int x,int y,int z) { return ch[x][z]=y,push_up(x); }
inline int new_node(int v,int x=0) { return x=++node_cnt,val[x]=v,key[x]=rnd(),cnt[x]=sz[x]=1,x; }
int merge(int x,int y)
{
if(!x||!y) return x+y;
if(key[x]<key[y]) return setc(x,merge(ch[x][1],y),1),x;
else return setc(y,merge(x,ch[y][0]),0),y;return 0;
}
pii splitk(int x,int k)
{
if(!x||!k) return mp(0,x);pii t;
if(k<=sz[ch[x][0]])
return t=splitk(ch[x][0],k),setc(x,t.sec,0),mp(t.fir,x);
else return k-=sz[ch[x][0]]+cnt[x],k=max(k,0),
t=splitk(ch[x][1],k),setc(x,t.fir,1),mp(x,t.sec);
return mp(0,0);
}
pii splitv(int x,int v)
{
if(!x) return mp(0,0);pii t;
if(val[x]<=v) return t=splitv(ch[x][1],v),setc(x,t.fir,1),mp(x,t.sec);
else return t=splitv(ch[x][0],v),setc(x,t.sec,0),mp(t.fir,x);
return mp(0,0);
}
inline int insert(int v)
{
pii a=splitv(rt,v),b=splitv(a.fir,v-1);
if(b.sec) cnt[b.sec]++,sz[b.sec]++;
else b.sec=new_node(v);
return rt=merge(merge(b.fir,b.sec),a.sec);
}
inline int del(int v)
{
pii a=splitv(rt,v),b=splitv(a.fir,v-1);
if(!b.sec||!(--cnt[b.sec])) return rt=merge(b.fir,a.sec);
return sz[b.sec]--,rt=merge(merge(b.fir,b.sec),a.sec);
}
inline int kth(int k)
{
pii t=splitk(rt,k);int x=t.fir;
while(ch[x][1]) x=ch[x][1];
return rt=merge(t.fir,t.sec),val[x];
}
inline int pre(int v)
{
pii t=splitv(rt,v-1);int x=t.fir;
while(ch[x][1]) x=ch[x][1];
return rt=merge(t.fir,t.sec),val[x];
}
inline int post(int v)
{
pii t=splitv(rt,v);int x=t.sec;
while(ch[x][0]) x=ch[x][0];
return rt=merge(t.fir,t.sec),val[x];
}
inline int rank(int v)
{
pii a=splitv(rt,v),b=splitv(a.fir,v-1);
int ans=sz[b.fir]+(b.sec>0);
return rt=merge(merge(b.fir,b.sec),a.sec),ans;
}
}s;
int main()
{
for(int n=inn();n;n--) switch(inn())
{
case 1:s.insert(inn());break;
case 2:s.del(inn());break;
case 3:printf("%d\n",s.rank(inn()));break;
case 4:printf("%d\n",s.kth(inn()));break;
case 5:printf("%d\n",s.pre(inn()));break;
case 6:printf("%d\n",s.post(inn()));break;
default:printf("TAT\n");
}
return 0;
}
bzoj 3223
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<utility>
#include<climits>
#define gc getchar()
#define ull unsigned long long
#define N 100010
#define mp make_pair
#define fir first
#define sec second
using namespace std;
typedef pair<int,int> pii;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int rt,node_cnt,ch[N][2],rev[N],val[N],key[N],sz[N],ans[N],c;
struct Rand{
ull x;Rand(){ x=0; }
inline ull operator()() { return (x*=998244353)^=1000000007; }
}rnd;
inline int new_node(int v,int x=0) { return x=++node_cnt,val[x]=v,key[x]=rnd(),sz[x]=1,x; }
inline int push_up(int x) { return sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; }
inline int setc(int x,int y,int z) { return ch[x][z]=y,push_up(x); }
inline int push_down(int x)
{
if(!rev[x]) return 0;
if(ch[x][0]) rev[ch[x][0]]^=1;
if(ch[x][1]) rev[ch[x][1]]^=1;
return swap(ch[x][0],ch[x][1]),rev[x]=0;
}
int merge(int x,int y)
{
if(!x||!y) return x+y;push_down(x),push_down(y);
if(key[x]<key[y]) return setc(x,merge(ch[x][1],y),1),x;
else return setc(y,merge(x,ch[y][0]),0),y;return 0;
}
pii split(int x,int k)
{
if(!x||!k) return mp(0,x);pii t;push_down(x);
if(k<=sz[ch[x][0]]) return t=split(ch[x][0],k),setc(x,t.sec,0),mp(t.fir,x);
else return t=split(ch[x][1],k-sz[ch[x][0]]-1),setc(x,t.fir,1),mp(x,t.sec);
}
inline int reverse(int l,int r)
{
pii a=split(rt,r),b=split(a.fir,l-1);
return rev[b.sec]^=1,rt=merge(merge(b.fir,b.sec),a.sec);
}
int build(int a,int b)
{
if(a>b) return 0;int c=(a+b)>>1,x=new_node(c);
return setc(x,build(a,c-1),0),setc(x,build(c+1,b),1),x;
}
int getans(int x) { return x?(push_down(x),getans(ch[x][0]),ans[++c]=val[x],getans(ch[x][1])):0; }
int main()
{
int n=inn(),m=inn();rt=build(1,n);
for(int l,r;m;m--) l=inn(),r=inn(),reverse(l,r);
getans(rt);
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
return !printf("\n");
}