Hdu1540Tunnel Warfare线段树

  

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <string>
#include <iostream>
#include <map>
#include <cstdlib>
#include <list>
#include <set>
#include <queue>
#include <stack>
#include<math.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 55555;
int sum[maxn << 2];
int lsum[maxn << 2];
int rsum[maxn << 2];
void up(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(max(sum[rt << 1], sum[rt << 1 | 1]), rsum[rt << 1] + lsum[rt << 1 | 1]);
}

void build(int l, int r, int rt)
{
    if (l == r){
        sum[rt] = lsum[rt] = rsum[rt] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    up(rt, r - l + 1);
}

void update(int key, int add, int l, int r, int rt)
{
    if (l == r){
        if (add) sum[rt] = lsum[rt] = rsum[rt] = 0;
        if (!add) sum[rt] = lsum[rt] = rsum[rt] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    if (key <= mid) update(key, add, lson);
    else update(key, add, rson);
    up(rt, r - l + 1);
}

int ask(int key, int l, int r, int rt)
{
    if (l == r){
        if (sum[rt] == 1) return 1; return 0;
    }
    int mid = (l + r) >> 1;
    int a = l + lsum[rt] - 1; int b = r - rsum[rt] + 1;
    int ans = 0;
    if (key >= l&&key <= a) ans = lsum[rt];
    if (key >= b&&key <= r) ans = max(ans, rsum[rt]);
    int c = mid - rsum[rt << 1] + 1; int d = lsum[rt << 1 | 1] + mid;
    if (key >= c&&key <= d) ans = max(ans, rsum[rt << 1] + lsum[rt << 1 | 1]);
    if (ans) return ans;
    if (key <= mid) return ask(key, lson);
    else return ask(key, rson);
}
int q[maxn<<1];
int main()
{
    int n, m;
    int a; char str[100];
    while (scanf("%d%d",&n,&m)!=EOF){
        build(1, n, 1);
        int ans = 0;
        for (int i = 0; i < m; i++){
            scanf("%s%d", str, &a);
            if (str[0] == ‘D‘){
                update(a, 1, 1, n, 1);
                q[ans++] = a;
            }
            if (str[0] == ‘Q‘){
                printf("%d\n", ask(a, 1, n, 1));
            }
            if (str[0] == ‘R‘){
                if(ans<=0) continue;
                int t = q[--ans];
                update(t, 0, 1, n, 1);
            }
        }
    }
    return 0;
}

Hdu1540Tunnel Warfare线段树,布布扣,bubuko.com

时间: 2024-10-10 02:25:51

Hdu1540Tunnel Warfare线段树的相关文章

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

POJ-2892-Tunnel Warfare(线段树)

Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was

hdu1540 Tunnel Warfare 线段树/树状数组

During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly con

hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1540 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Gene

HDU 1540 Tunnel Warfare 线段树区间合并

Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区间,左儿子的最大连续右区间+右儿子的最大连续左区间)决定 所以线段树的节点应该维护当前节点的最大连续左区间,最大连续右区间,和最大连续区间. 注意更新的时候,如果左儿子全满,父亲节点的左连续区间还要加上右儿子的左区间.反之同理. 查询的时候,可以剪枝,如果是叶子,或为空,或满,则不用往下查询. 查询

hdu 1540 Tunnel Warfare(线段树)

题目链接:hdu 1540 Tunnel Warfare 题目大意:有连续的N个城镇,三种操作: D x:第x城镇被破坏 Q x:插叙第x城镇所在联通块有多少个城镇没有被破坏 R:修复最后一个被破坏的城镇 解题思路:线段树区间合并,每个城镇看成一个叶子节点,用一个vector记录破坏顺序.对于查询来说,每次只要判断是否在mid?R[lson(u)],mid+L[rson(u)]之间即可,否则即递归查询左右子树. #include <cstdio> #include <cstring>

HDU 1540 Tunnel Warfare(线段树单点更新+区间合并)

Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every vill

HDU 1540 Tunnel Warfare (线段树或set水过)

题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. 析:首先可以用set水过,set用来记录每个被破坏的村庄,然后查找时,只要查找左右两个端点好. 用线段树的话,就维护三个值分别是左端点连续右端点连续,全连续的最长的区别,然后用线段树维护就好. 代码如下: set过: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #includ

poj2892--Tunnel Warfare(线段树)

题目链接:点击打开链接 题目大意:给出n个格子,三种操作,D k:消除第k个格子,R:恢复最后一次消除的格子,Q k:问和k相连的最长连续序列. 求最长连续序列,线段树统计每段中被消除的最大点和最小点,更新点k,查询段[1,k][k,n],然后相减得到结果 #include <cstdio> #include <cstring> #include <stack> #include <algorithm> using namespace std ; #defi