1. 程式人生 > >鬼子進村[樹狀陣列+二分答案]

鬼子進村[樹狀陣列+二分答案]

傳送門 

[樹狀陣列+二分答案]

如果被封鎖,就在樹狀數組裡插入1

然後每次查詢二分找前面和後面第一個為1的地方就可以了

對於修復,用一個棧維護

複雜度O(nlogn^2)


#include<bits/stdc++.h>
#define N 50050
using namespace std;
int n,m,c[N],sta[N],top,vis[N];
void Up(int x,int val){for(;x<=n;x+=x&-x)c[x]+=val;}
int Q(int x){int ans=0; for(;x;x-=x&-x)ans+=c[x]; return ans;}
int Q_l(int x){
	int l=0,r=x;
	while(l<r){ 	
		int mid=(l+r)>>1;
		if(Q(x)-Q(mid)>=1) l=mid+1;
		else r=mid;
	}return l;
}
int Q_r(int x){
	int l=x,r=n+1;
	while(l<r){
		int mid=(l+r)>>1;
		if(Q(mid)-Q(x)>=1) r=mid;
		else l=mid+1;
	}return l;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		char s[3]; scanf("%s",s);
		if(s[0]=='D'){
			int x; scanf("%d",&x);
			Up(x,1); sta[++top]=x , vis[x]=1;
		}
		if(s[0]=='R') vis[sta[top]]=0,Up(sta[top--],-1);
		if(s[0]=='Q'){
			int x; scanf("%d",&x);
			int Left=Q_l(x),Right=Q_r(x);
			if(vis[x]) printf("0\n");
			else printf("%d\n",Right-Left-1);
		}
	}return 0;
}