HDU 1540 (区间合并)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 50010
#define Lson root*2
#define Rson root*2+1
#define Max(a,b)(a>b?a:b)
int ac[maxn];
struct ndoe
{//lsum表示左区间的连续,rsum表示在右区间的连续,sum表示中间区间的连续;
    int L,R;
    int lsum,rsum,sum;
    int Mid()
    {
        return (R+L)/2;
    }
    int len()
    {
        return (R-L+1);
    }
} a[maxn*4];
void BuildTree(int root,int L,int R)
{
    a[root].L=L,a[root].R=R;
    a[root].lsum = a[root].rsum = a[root].sum = a[root].len();
    if(L==R) return ;
    BuildTree(Lson,L,a[root].Mid());
    BuildTree(Rson,a[root].Mid()+1,R);
}
void pushup(int root)
{
    a[root].lsum = a[Lson].lsum, a[root].rsum = a[Rson].rsum;//左区间的连续 最大为子节点的最大连续,右区间同理;

    if(a[Lson].lsum == a[Lson].len())                       //如果子节点的最大连续等于其长度,则说明其最大连续可以加上右区间的左连续;
        a[root].lsum = a[Lson].lsum + a[Rson].lsum;
    if(a[Rson].rsum == a[Rson].len())
        a[root].rsum = a[Rson].rsum + a[Lson].rsum;

    a[root].sum = Max(a[root].lsum, Max(a[root].rsum, a[Lson].rsum+a[Rson].lsum));//中间区间的最大为三个数的最大值(左连续,右连续,子节点左区间的右连续+右区间的左连续)
}
void update(int root, int k, int e)
{
    if( a[root].L == a[root].R )
    {
        a[root].lsum = a[root].rsum = a[root].sum = e;
        return ;
    }

    if(k <= a[root].Mid())
        update(Lson, k, e);
    else
        update(Rson, k, e);

    pushup(root);
}
int Query(int root,int k)
{
    if(a[root].sum ==0 )
        return 0;
    if(k < a[root].L +a[root].lsum)    //判断其是否在左区间;K < 左端点 + 左连续;
        return a[root].lsum;
    if(k > a[root].R - a[root].rsum)  //判断其是否在右区间; k > 右端点 - 右连续;
        return a[root].rsum;
    if(k > (a[Lson].R - a[Lson].rsum) && k < (a[Rson].L + a[Rson].lsum)) //判断是否在中间; 右端点 - 右连续 < K < 左端点 + 左连续;
        return a[Rson].lsum + a[Lson].rsum;
    if(k<=a[root].Mid())
        return Query(Lson,k);
    else
        return Query(Rson,k);
}
int main()
{
    int n,m,k,w;
    char str[10];
    while(~scanf("%d%d",&n,&m))
    {
        k=0;
        BuildTree(1,1,n);
        while(m--)
        {
            scanf("%s",str);
            if(str[0]==‘D‘)
            {
                scanf("%d",&w);
                ac[k]=w;
                update(1,w,0);
                k++;
            }
            if(str[0]==‘R‘)
            {
                k--;
                w = ac[k];
                update(1,w,1);
            }
            if(str[0] == ‘Q‘)
            {
                scanf("%d",&w);
                printf("%d\n",Query(1,w));
            }
        }
    }
    return 0;
}
时间: 2024-10-29 02:00:15

HDU 1540 (区间合并)的相关文章

Tunnel Warfare HDU 1540 区间合并+最大最小值

Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里巧妙使用了最大值最小值来进行区间的查找.上一行是大佬的详细题解,真的很妙啊. 代码实现 #include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define ls (rt&l

HDU 3911 区间合并求最大长度的问题

http://vjudge.net/problem/viewProblem.action?id=21557 题目大意: 每进行一次颜色改变都可以把一段区间内的黑石头变成白石头,白石头变成黑石头,最后问区间内黑石头连续的最大长度 这里我们可以用rev[]作为lazy标记,每次进行改变,rev[]^1 因为有黑白两种石头,我们求连续区间,需要维护黑,白两种石头的左侧最多,右侧最多和全部最多,所以我们这里可以用一个二维数组进行描述 每次做出改变,只要将黑白石头的值进行交换即可就方便了很多 对于最后访问

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 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/POJ 2892 Tunnel Warfare 【线段树区间合并】

Tunnel Warfare                                                             Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) 链接:hdu 1540        POJ 2892 Problem Description During the War of Resistance Against Japan,

HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并

Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast

HDU 1540 Tunnel Warfare 线段树:单点更新,区间合并

Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast

HDU 1540 POJ 2892 线段树区间合并

给出N个点,M次操作,N个点开始在一条线上链式相连 D操作  把某点删除掉 Q操作  询问某点一共可以连接多少个点 R操作  把上一次删除的点还原 线段树处理区间合并 分别记录每个区间的左端连续最长和右端连续最长 #include "stdio.h" #include "string.h" struct node { int l,r,lx,rx,x; }data[200010]; int mark[50100]; int Max(int a,int b) { if

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