码迷,mamicode.com
首页 > 编程语言 > 详细

POJ 2892 Tunnel Warfare [树状数组]

时间:2015-05-27 22:51:55      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!