POJ 2892 Tunnel Warfare [树状数组]

来源:互联网 发布:淘宝网店营销推广 编辑:程序博客网 时间:2024/05/02 00:38

题目链接: 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 treevoid add(int s[],int i,int x){    for(;i<=m;i += -i&i)s[i] += x;}// sum of bit treeint 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 / 0001int 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 / 1000int 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;}


0 0
原创粉丝点击