Benzenesir @ 2022-08-30 12:16:41
是这样的,我自己测试样例,发现有时候能输出正确,有时候答案是错的,有时候在 5 8 这里就不动了,求dalao赐教
#include <iostream>
#include <queue>
#include <time.h>
#include <string.h>
using namespace std;
const int maxN=2*1e6+10;
int n,m; int r1=0,r2=0,r3=0;
int son[maxN][2],fa[maxN],size[maxN],val[maxN],data[maxN],root,idx;
int rd[maxN];
queue<int> rb;
inline void update(int x){
if(x==0) return ;
size[x]=size[son[x][1]]+size[son[x][0]]+1;
//cout << x << endl;
//cout << size[son[x][1]] << " " << size[son[x][0]] << endl;
}
inline void split(int now,int k,int &x,int &y){//按权值分裂,小于等于k的分到左子树,大于的分到右子树
if(!now){
x=y=0;
}
else{
if(data[now]<=k){
x=now;
split(son[now][1],k,son[now][1],y);//这里我们已经把x更新为now了,由于treap的结构坚不可摧,所以右子树都是大于now的,所以再合并时就把其合并到now的右儿子上
}
else{
y=now;
split(son[now][0],k,x,son[now][0]);
}
}
update(now);
}
inline int merge(int a,int b){
if(!a||!b) return a+b;
if(val[a]<val[b]){
son[a][1]=merge(son[a][1],b);//将右子树和b合并,作为a的新右子树
update(a);
return a;
}
else{
son[b][0]=merge(a,son[b][0]);//同理
update(b);
return b;
}
}
inline int new_point(int v){
int p;
if(!rb.empty()) {
p=rb.front();
rb.pop();
}
else p=++idx;
size[p]=1;
val[p]=rand();
while(rd[val[p]]) val[p]=rand();
rd[val[p]]=1;
data[p]=v;
//cout << size[p] << " " << val[p] << " " << data[p] << endl;
return p;
}
inline void insert(int x){
int r1,r2;
split(root,x,r1,r2);
root=merge(merge(r1,new_point(x)),r2);
}
inline void del(int x){//就算x不在bst里面,我们也能通过split找到它
int r1,r2,r3;
split(root,x,r1,r2);
split(r1,x-1,r1,r3);
rb.push(r3);
r3=merge(son[r3][0],son[r3][1]);
root=merge(merge(r1,r3),r2);
}
inline int inrank(int x){
int r1,r2;
int ans;
split(root,x-1,r1,r2);
ans=size[r1]+1;
root=merge(r1,r2);
return ans;
}
inline int kth(int k){
int now=root;
while(1){
if(size[son[now][0]]<k&&size[son[now][0]]+1>=k){
return data[now];
}
if(size[son[now][0]]>=k){
now=son[now][0];
}
else{
k-=size[son[now][0]]+1,now=son[now][1];
}
}
}
inline int pre(int x){
return kth(inrank(x)-1);
}
inline int suffix(int x){
return kth(inrank(x+1));//这里我们将值加一,其排名一定是最小的严格大于x的数的排名
}
signed main(){
//freopen("P6136_1.in","r",stdin);
//freopen("FHQ.out","w",stdout);
//memset(size,0,sizeof(size));
srand(time(0));
ios::sync_with_stdio(false);//cin加速
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);//再度加速
//不能用printf,scanf
cin >> n >> m;
for(int i=1;i<=n;i++){
int x;cin >> x;
insert(x);
// cout << size[root] << endl;
}
int last=0,ans;
//del(4);
//insert(9);
//cout << inrank(10) << endl;
while(m--){
//cout << data[root] << endl;
int opt,x;
cin >> opt >> x;
x^=last;
//cout << x << endl;
switch (opt){
case 1:
insert(x);
break;
case 2:
del(x);
break;
case 3:
last=inrank(x);
// cout << last << endl;
ans^=last;
break;
case 4:
last=kth(x);
// cout << last << endl;
ans^=last;
break;
case 5:
last=pre(x);
//cout << inrank(x) << endl;
//cout << last << endl;
ans^=last;
break;
case 6:
last=suffix(x);
// cout << last << endl;
ans^=last;
break;
}
}
cout << ans << endl;
return 114514-114514;
}
/*
treap中,由于随机值的存在,所以bst中的每一个节点只代表一个数,相同的数会被分配到不同的节点中,不像splay需要维护cnt
*/
by Benzenesir @ 2022-09-03 00:07:36
Rebuild已A,磁铁完结