标签:
题目链接: http://poj.org/problem?id=2892
题意:一个长度为n的线段,下面m个操作
D x 表示将单元x毁掉
R 表示修复最后毁坏的那个单元
Q x 询问这个单元以及它周围有多少个连续的单元,如果它本身已经被毁坏了就是0
思路:
这道题是经典的线段树入门题目,由于只是进行单点更新, 不涉及区间更新,用树状数组更简洁。
维护两个树状数组,一个是把所有的1进行维护,一个是把所有的0进行维护。
翻转(炸毁或修复)任何一个单元,同时修改这两个树状数组,仅仅是为了 合并 和 分裂 操作的简便处理。
求连续是1的区间时,利用树状数组记录部分和的特点,进行跨越式的搜索左右边界。
#include<vector> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<algorithm> #include<queue> #include<ctime> #define FOR(i,a,b) for(int i=a;i<b;i++) #define FORE(i,a,b) for(int i=a;i<=b;i++) #define MST(a,b) memset(a,b,sizeof(a)) #define SCF(a) scanf("%d",&a) #define SCFS(a) scanf("%s",a) #define SCF2(a,b) scanf("%d%d",&a,&b) #define SCF3(a,b,c) scanf("%d%d%d",&a,&b,&c) using namespace std; typedef long long int Uint; const int N = 50000+5; int m; int mat[N]; int s[2][N]; // add to bit tree void add(int s[],int i,int x){ for(;i<=m;i += -i&i)s[i] += x; } // sum of bit tree int Sum(int s[],int i){ int ans = 0; for(;i>=1;i -= -i&i)ans += s[i]; return ans; } //the right boundary of consective value. 1110 / 0001 int nxt(int s[],int j){ int tmp,sj = Sum(s,j); for(int i = j;i<=m;i += -i&i) if((tmp = Sum(s,i)) == sj + i - j) j = i,sj = tmp; else break; if(j == m) return j; if(Sum(s,j+1) != sj+1)return j; return nxt(s,j+1); } //the left boundary of consective value. 0111 / 1000 int pre(int s[],int j){ int tmp,sj = Sum(s,j); for(int i = j;i>=1;i -= -i&i) if((tmp = Sum(s,i)) == sj + i - j) j = i,sj = tmp; else break; if(Sum(s,j-1) != sj-1) return j+1; if(j == 1) return j; return pre(s,j-1); } void flip(int j){ add(s[mat[j]],j,-1);// exclude from self add(s[mat[j]^1],j,1);// include from oppo mat[j] ^= 1; } int lis[N]; int main(){ int q,b,ans; char ch[2]; // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(SCF2(m,q)!=EOF){ MST(s,0); FORE(j,1,m) add(s[mat[j] = 1],j,1); lis[0] = 0; while(q--){ SCFS(ch); if(ch[0]=='R'){ if(lis[0]){ if(!mat[lis[lis[0]]]) flip(lis[lis[0]]); lis[0]--; } continue; } else SCF(b); if(ch[0]=='D'){ if(mat[b])flip(b); lis[++lis[0]] = b; continue; } if(mat[b]) { int u = nxt(s[1],b); int v = pre(s[1],b); ans = u - v + 1; } else ans = 0; printf("%d\n",ans); } } return 0; }
POJ 2892 Tunnel Warfare [树状数组]
标签:
原文地址:http://blog.csdn.net/kevinkitty_love/article/details/46054471