POJ 2892 Tunnel Warfare [树状数组]

题目链接: 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;
}
时间: 2024-08-08 16:47:44

POJ 2892 Tunnel Warfare [树状数组]的相关文章

POJ 2892 Tunnel Warfare (树状数组+二分)

题目大意: 三个操作 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>

HDU 1540 &amp;&amp; POJ 2892 Tunnel Warfare (线段树,区间合并).

~~~~ 第一次遇到线段树合并的题,又被律爷教做人.TAT. ~~~~ 线段树的题意都很好理解吧.. 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1540 http://poj.org/problem?id=2892 ~~~~ 我的代码:200ms #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #defin

hdu 1541/poj 2352:Stars(树状数组,经典题)

Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4052    Accepted Submission(s): 1592 Problem Description Astronomers often examine star maps where stars are represented by points on a plan

poj 2155 二维树状数组

http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17721   Accepted: 6653 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. I

poj 2309 BST 使用树状数组的lowbit

如果领悟了树状数组中的lowbit,这道题就是极其简单的,最底层都是奇数,用lowbit(x)寻找x的父亲,然后x的父亲-1就是最大数 至于lowbit是如何计算的嘛,寻找x的父亲,其实就是x+2^x的二进制末尾0的个数. #include<iostream> #include<stdio.h> using namespace std; typedef long long ll; ll lowbit(int x){ return x&(-x); } int main(){

poj 1195 二维树状数组 及二维树状数组模板

http://poj.org/problem?id=1195 求矩阵和的时候,下标弄错WA了一次... 求矩形(x1,y1) (x2,y2)的sum |sum=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1) 二维树状数组讲解:http://blog.csdn.net/u011026968/article/details/38532117 二维树状数组模板: /*========================================

poj 2299 Ultra-QuickSort 离散化 + 树状数组

题目链接:http://poj.org/problem?id=2299 离散化 + 树状数组 教科书例题般的题目 #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <vector> #include <stack> #include <set> #include

poj 2299 Ultra-QuickSort (树状数组+离散化)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 48257   Accepted: 17610 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

POJ 3321 Apple Tree (树状数组)

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21191   Accepted: 6436 Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been