apple_vinegar @ 2024-11-06 16:05:03
#include<bits/stdc++.h>
#define int long long
#define mid ((l+(r-l)>>1))
#define ls (p<<1)
#define rs (ls|1)
#define lt ls,l,mid
#define rt rs,mid,r
using namespace std;
const int INF=1e15,N=1e5+5;
int last,tot,root,ans;
inline int read(){
int a=1,b=0;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') a=-a;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
b=(b<<1)+(b<<3)+(ch^48);
ch=getchar();
}
return a*b;
}
struct node{
int l,r;
int val,dat;
int cnt,size;
};
node a[N];
inline int add(int val){
a[++tot].val=val;
a[tot].dat=rand();
a[tot].cnt=a[tot].size+1;
return tot;
}
inline void update(int p){
a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;
}
inline void build(){
add(-INF),add(INF);
root=1,a[1].r=2;
update(root);
}
inline void zig(int &p){//right
int q=a[p].l;
a[p].l=a[q].r;
a[q].r=p;
p=q;
update(a[p].r),update(p);
}
inline void zag(int &p){//left
int q=a[p].r;
a[p].r=a[q].l;
a[q].l=p;
p=q;
update(a[p].l),update(p);
}
inline void insert(int &p,int val){
if(p==0){
p=add(val);
return;
}
if(val==a[p].val){
a[p].cnt++;
update(p);
return ;
}
if(val<a[p].val){
insert(a[p].l,val);
if(a[p].dat<a[a[p].l].dat){
zig(p);
}
}
else{
insert(a[p].r,val);
if(a[p].dat<a[a[p].r].dat) zag(p);
}
update(p);
}
inline void remove(int &p,int val){
if(p==0) return ;
if(val==a[p].val){
if(a[p].cnt>1){
a[p].cnt--;
update(p);
return;
}
if(a[p].l||a[p].r){
if(!a[p].l||a[a[p].l].dat>a[a[p].r].dat){
zig(p);
remove(a[p].r,val);
}
else{
zag(p);
remove(a[p].l,val);
}
update(p);
}
else p=0;
return;
}
if(val<a[p].val) remove(a[p].l,val);
else remove(a[p].r,val);
update(p);
}
inline int findrank(int p,int val){
if(p==0) return 0;
if(val==a[p].val) return a[a[p].l].size+1;
if(val<a[p].val) return findrank(a[p].l,val);
else return findrank(a[p].r,val)+a[a[p].l].size+a[p].cnt;
}
inline int findwho(int p,int rank){
if(p==0) return INF;
if(a[a[p].l].size>=rank) return findwho(a[p].l,rank);
if(a[a[p].l].size+a[p].cnt>=rank) return a[p].val;
return findwho(a[p].r,rank-a[a[p].l].size-a[p].cnt);
}
inline int getpre(int val){
int ans=1;
int p=root;
while(p){
if(val==a[p].val){
if(a[p].l>0){
p=a[p].l;
while(a[p].r>0) p=a[p].r;
ans=p;
}
break;
}
if(a[p].val<val&&a[p].val>a[ans].val) ans=p;
if(val<a[p].val) p=a[p].l;
else p=a[p].r;
}
return a[ans].val;
}
inline int getnext(int val){
int ans=2;
int p=root;
while(p){
if(val==a[p].val){
if(a[p].r>0){
p=a[p].r;
while(a[p].l>0) p=a[p].l;
ans=p;
}
break;
}
if(a[p].val>val&&a[p].val<a[ans].val) ans=p;
if(val<a[p].val) p=a[p].l;
else p=a[p].r;
}
return a[ans].val;
}
signed main(){
// freopen("a","w",stdout);
srand(time(0));
int n=read(),m=read();
build();
for(int i=1;i<=n;i++) insert(root,read());
while(m--){
int op=read(),x=read();
x^=last;
if(op==1){
insert(root,x);
}
if(op==2){
remove(root,x);
}
if(op==3){
last=(findrank(root,x)-1);
}
if(op==4){
last=findwho(root,x+1);
}
if(op==5){
last=getpre(x);
}
if(op==6){
last=getnext(x);
}
cout<<last<<endl;
if(op>=3) ans^=last;
// cout<<last<<endl;
}
cout<<ans;
return 0;
}
by Hagasei @ 2024-11-06 17:07:58
@penggc16801
N 开到 1.1e6+5
add 内 cnt 与 size 赋初值改为 a[tot].cnt=a[tot].size=1;
remove 内判断 zig 条件改为 !a[p].r||a[p].l&&a[a[p].l].dat>a[a[p].r].dat
findrank 内结点为空时应返回 1。
by Hagasei @ 2024-11-06 17:08:24
然后即可 ac。
by Hagasei @ 2024-11-06 17:12:05
以及 getpre 和 getnext 可以通过 findrank findwho 直接表示的,不用单独写函数。
by apple_vinegar @ 2024-11-06 17:12:20
@Hagasei %%%,可以问一下,第三点为什么已经特判了为叶子节点的情况还要加
a[p].l&&
吗?
by apple_vinegar @ 2024-11-06 17:15:38
等等,唐了,thx
by apple_vinegar @ 2024-11-06 17:20:41
@Hagasei 是用二分找到数再findrank吗?
by Hagasei @ 2024-11-06 17:38:01
@penggc16801 pre(x)=findwho(findrank(x)-1)
by chen_z @ 2024-11-06 17:42:31
@penggc16801 大佬您太巨了%%%
by HourSkit @ 2024-11-06 20:13:43
%%%