思路1:
树状数组+二分
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r #define mem(a,b) memset(a,b,sizeof(a)) const int N=5e4+5; int bit[N]; bool vis[N]; int n; int add(int x,int a){ while(x<=n)bit[x]+=a,x+=x&-x; } int query(int x){ int ans=0; while(x)ans+=bit[x],x-=x&-x; return ans; } bool check(int x,int m){ //cout<<query(m)<<' '<<query(x-1)<<endl; if(query(m)-query(x-1)<m-x+1)return true; else return false; } bool check1(int x,int m){ if(query(x)-query(m-1)<x-m+1)return true; else return false; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int m,x; char c; while(cin>>n>>m) { mem(bit,0); mem(vis,false); for(int i=1;i<=n;i++)add(i,1); stack<int>s; for(int i=1;i<=m;i++){ cin>>c; if(c=='D'){ cin>>x; if(!vis[x])add(x,-1),vis[x]=true; s.push(x); } else if(c=='Q'){ cin>>x; int l=x,r=n,mid=(l+r)>>1; while(l<r){ //cout<<l<<' '<<r<<' '<<query(mid)<<' '<<query(x-1)<<endl; if(check(x,mid))r=mid-1; else l=mid; mid=(l+r+1)>>1; } int R=mid; l=1,r=x,mid=(l+r)>>1; while(l<r){ if(check1(x,mid))l=mid+1; else r=mid; mid=(l+r)>>1; } int L=mid; if(vis[x])cout<<0<<endl; else cout<<R-L+1<<endl; } else{ if(vis[s.top()])add(s.top(),1),vis[s.top()]=false; s.pop(); } } } return 0; }
思路2:
线段树区间合并
代码:
#include<bits/stdc++.h> using namespace std; #define pb push_back #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r #define mem(a,b) memset(a,b,sizeof(a)) const int N=5e4+5; struct tree{ int ll,rr,len;//ll表示以当前区间左端点为左端点最长连续区间的长度,rr表示以当前区间右端点为右端点最长连续区间的长度,len表示当前区间的长度 }tree[N<<2]; void push_up(int rt){ if(tree[rt<<1].ll==tree[rt<<1].len)tree[rt].ll=tree[rt<<1].ll+tree[rt<<1|1].ll; else tree[rt].ll=tree[rt<<1].ll; if(tree[rt<<1|1].rr==tree[rt<<1|1].len)tree[rt].rr=tree[rt<<1|1].rr+tree[rt<<1].rr; else tree[rt].rr=tree[rt<<1|1].rr; } void build(int rt,int l,int r){ tree[rt].ll=tree[rt].rr=tree[rt].len=r-l+1; if(l==r)return ; int m=(l+r)>>1; build(ls); build(rs); } void update(int p,int v,int rt,int l,int r){ if(l==r){ tree[rt].ll=tree[rt].rr=v; return ; } int m=(l+r)>>1; if(p<=m)update(p,v,ls); else update(p,v,rs); push_up(rt); } int query(int p,int rt,int l,int r){ if(rt==1){ if(l+tree[rt].ll-1>=p)return tree[rt].ll; if(r-tree[rt].rr+1<=p)return tree[rt].rr; } else{ if(l+tree[rt].ll-1>=p)return tree[rt].ll+tree[rt-1].rr; if(r-tree[rt].rr+1<=p)return tree[rt].rr+tree[rt+1].ll; } if(l==r)return 0; int m=(l+r)>>1; if(p<=m)return query(p,ls); else return query(p,rs); } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,m,x; char c; while(cin>>n>>m){ stack<int>s; build(1,1,n); while(m--){ cin>>c; if(c=='D'){ cin>>x; s.push(x); update(x,0,1,1,n); } else if(c=='Q'){ cin>>x; cout<<query(x,1,1,n)<<endl; } else{ x=s.top(); s.pop(); update(x,1,1,1,n); } } } return 0; }