思路:
左右可以开动态节点的线段。
我们考虑建一棵节点很多的线段树,动态更新区间长度。
维护的是gcd。
pushup操作需要特判节点是否被使用过。
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
const int maxn = 6e5+500;
int l,r,op,tree[maxn<<2];
inline void pushup(int rt){
if(tree[ls]==-1&&tree[rs]==-1) tree[rt] = -1;
if(tree[ls]==-1&&tree[rs]!=-1) tree[rt] = tree[rs];
if(tree[ls]!=-1&&tree[rs]==-1) tree[rt] = tree[ls];
if(tree[ls]!=-1&&tree[rs]!=-1) tree[rt] = __gcd(tree[ls],tree[rs]);
}
void build(int l,int r,int rt){
if(l==r){
tree[rt] = -1;
return ;
}
int mid = l+r>>1;
build(l,mid,ls);
build(mid+1,r,rs);
pushup(rt);
}
int update(int l,int r,int rt,int pos,int val){
if(l==r){
int tmp = tree[rt];
tree[rt] = val;
return tmp;
}
int mid = l+r>>1,res;
if(pos<=mid) res = update(l,mid,ls,pos,val);
else res = update(mid+1,r,rs,pos,val);
pushup(rt);
return res;
}
int main(){
scanf("%d",&op);
l = 200000;
r = l-1;
build(1,maxn,1); //建立一棵[1,maxn]的线段树,但是只在l,r更新
map<int,int> mp; //通过map来存有没有被访问过
while(op--){
char o;
int x;
cin>>o;
if(o=='?'){
if(mp[tree[1]]>0) cout<<"Y"<<tree[1]<<endl;
else cout<<"N"<<endl;
}else if(o=='+'){
cin>>x;
mp[x]++;
r++;
update(1,maxn,1,r,x);
}else if(o=='-'){
x = update(1,maxn,1,l,-1);
mp[x]--;
l++;
}
}
return 0;
}