题目大意:
三个操作
D pos 将pos位置摧毁,让它和周围不相连。
Q pos 问和pos 相连的有多少个村庄。
R 修复最近摧毁的村庄。
思路分析:
树状数组记录这个区间有多少个1。
如果 [s-e] 有e-s+1个1 的话。那么这个区间是相连的。
这样的话,我们就可以用二分的办法求出与某个位置最大相连的数量。
还有这里二分
while(l<=r)
{
if(满足)
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define maxn 55555 using namespace std; int n,m; int c[maxn]; int lowbit(int x) { return (x&(-x)); } int sum(int x) { int ret=0; while(x>0) { ret+=c[x]; x-=lowbit(x); } return ret; } void add(int x,int d) { while(x<=n) { c[x]+=d; x+=lowbit(x); } } int top; int stack[maxn]; int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(c,0,sizeof c); for(int i=1;i<=n;i++) { add(i,1); } char str[5]; while(m--) { scanf("%s",str); if(str[0]=='D') { int pos; scanf("%d",&pos); // if(sum(pos)-sum(pos-1)==0)continue; add(pos,-1); stack[top++]=pos; } else if(str[0]=='R') { int pos=stack[--top]; add(pos,1); } else { int cur,l,r,ans,rs,re; scanf("%d",&cur); if(sum(cur)-sum(cur-1)==0) { printf("0\n"); continue; } l=cur;r=n; while(l<=r) { int mid=(l+r)>>1; if(sum(mid)-sum(cur-1)==mid-cur+1) { ans=mid; l=mid+1; } else r=mid-1; } re=ans; l=1;r=cur; while(l<=r) { int mid=(l+r)>>1; if(sum(cur)-sum(mid-1)==cur-mid+1) { ans=mid; r=mid-1; } else l=mid+1; } rs=ans; // printf("%d %d\n",re,rs); printf("%d\n",re-rs+1); } } } return 0; }
POJ 2892 Tunnel Warfare (树状数组+二分)
时间: 2024-12-21 14:43:28