首页 > 代码库 > POJ--2892--Tunnel Warfare【线段树】区间合并

POJ--2892--Tunnel Warfare【线段树】区间合并

链接:http://poj.org/problem?id=2892

题意:有n个村庄排成一排,三种操作:
1. D x 摧毁村庄x
2. Q x 询问村庄x的最长一段没有被摧毁的村庄数量
3. R   恢复上一个被摧毁的村庄


思路:线段树区间合并,lsum记录当前节点往左的最长连续距离,rsum记录当前节点往右的最长连续距离。


#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 50100
#define eps 1e-7
#define INF 0x3F3F3F3F      //0x7FFFFFFF
#define LLINF 0x3F3F3F3F3F3F3F3F    //0x7FFFFFFFFFFFFFFF
#define seed 1313131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

int sum[MAXN << 2], lsum[MAXN << 2], rsum[MAXN << 2];
int num[MAXN];
int n;
void pushup(int rt, int m){
    lsum[rt] = lsum[rt << 1];
    rsum[rt] = rsum[rt << 1 | 1];
    if(lsum[rt] == (m - (m >> 1)))    lsum[rt] += lsum[rt << 1 | 1];
    if(rsum[rt] == (m >> 1))    rsum[rt] += rsum[rt << 1];
    sum[rt] = max(lsum[rt << 1 | 1] + rsum[rt << 1], max(sum[rt << 1], sum[rt << 1 | 1]));
}
void build(int l, int r, int rt){
    sum[rt] = lsum[rt] = rsum[rt] = r - l + 1;
    if(l == r)  return ;
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
}
void update(int k, int c, int l, int r, int rt){
    if(l == r){
        sum[rt] = lsum[rt] = rsum[rt] = c;
        return ;
    }
    int m = (l + r) >> 1;
    if(k <= m)  update(k, c, lson);
    else    update(k, c, rson);
    pushup(rt, r - l + 1);
}
int query(int pos, int l, int r, int rt){
    if(l == r)  return sum[rt];
    int m = (l + r) >> 1;
    if(m >= pos){
        if(pos >= m - rsum[rt << 1] + 1)    return lsum[rt << 1 | 1] + rsum[rt << 1];
        else    return query(pos, lson);
    }
    else{
        if(pos <= m + lsum[rt << 1 | 1] + 1)    return lsum[rt << 1 | 1] + rsum[rt << 1];
        else    return query(pos, rson);
    }
}
stack<int>s;
int main(){
    int i, j, m, c;
    char str[5];
    while(scanf("%d%d", &n, &m) != EOF){
        build(1, n, 1);
        while(!s.empty())   s.pop();
        memset(num, 0, sizeof(int) * (n + 5));
        while(m--){
            scanf("%s", str);
            if(str[0] == 'R'){
                if(!s.empty()){
                    c = s.top();
                    s.pop();
                    num[c]--;
                    if(num[c] == 0) update(c, 1, 1, n, 1);
                }
            }
            else{
                scanf("%d", &c);
                if(str[0] == 'D'){
                    if(num[c] == 0) update(c, 0, 1, n, 1);
                    num[c]++;
                    s.push(c);
                }
                else{
                    if(num[c]){
                        puts("0");
                        continue;
                    }
                    printf("%d\n", query(c, 1, n, 1));
                }
            }
        }
    }
    return 0;
}


POJ--2892--Tunnel Warfare【线段树】区间合并