题目链接: 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;
}