Tunnel Warfare HDU - 1540(线段树最长连续区间)

Posted wtsruvf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tunnel Warfare HDU - 1540(线段树最长连续区间)相关的知识,希望对你有一定的参考价值。

题意:

一条线上的点,D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点。
 
解析:
线段树结点 设置一个  lq记录区间左端点开始的最大连续个数,  rq 记录区间右端点开始的最大的连续个数
其它和原来一样即可
看代码吧。。。
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 1000010, INF = 0x7fffffff;
typedef long long LL;
int a, b, x, y, ans;

struct node{
    int l, r, w, lq, rq;
}Node[maxn];

void build(int k, int ll, int rr)
{
    Node[k].l = ll, Node[k].r = rr;
    if(Node[k].l == Node[k].r)
    {
        Node[k].lq = Node[k].rq = Node[k].w = 1;
        return;
    }
    int m = (ll + rr) / 2;
    build(k*2, ll, m);
    build(k*2+1, m+1, rr);
    Node[k].lq = Node[k].rq = Node[k].w = Node[k*2].w + Node[k*2+1].w;
}

void chp(int k)  //单点修改
{
    if(Node[k].l == Node[k].r)
    {
        Node[k].lq = Node[k].rq = Node[k].w = y;
        return;
    }
    int m = (Node[k].l + Node[k].r) / 2;
    if(x <= m) chp(k*2);
    else chp(k*2+1);
    Node[k].w = Node[k*2].w + Node[k*2+1].w;
    Node[k].lq = Node[k*2].lq;           //修改后初始化 父结点的最长连续左区间 为 左子结点的最长连续左区间
    Node[k].rq = Node[k*2+1].rq;         //父结点的最长连续右区间 为 右子结点的最长连续右区间
    if(Node[k*2].lq == Node[k*2].r - Node[k*2].l + 1)  //如果左子结点的最长连续左区间 为整个区间的长度 那么父结点的最长连续左区间 应该 加上 右子结点的最长连续右区间
        Node[k].lq += Node[k*2+1].lq;
    if(Node[k*2+1].rq == Node[k*2+1].r - Node[k*2+1].l + 1) // 同理
        Node[k].rq += Node[k*2].rq;
}

void qinter(int k, int t)
{
    if(Node[k].l == Node[k].r || Node[k].w == 0 || Node[k].w == Node[k].r - Node[k].l + 1) //如果当前区间为单点、区间和为0、区间和为区间长度 那么就没必要往下搜了 返回即可
    {
        ans += Node[k].w;
        return;
    }
    int m = (Node[k].l + Node[k].r) / 2;
    if(t <= m)   //如果t在左子树
    {
        if(t >= Node[k*2].r - Node[k*2].rq + 1)  //如果t大于左子树右区间的左端点 说明t在左子树的右区间内
        {
            ans += (Node[k*2].rq + Node[k*2+1].lq);  //然后用左子树的最长连右区间 + 右子树的最长连续左区间
            return;
        }
        else
            qinter(k*2, t);  //如果不在右区间 则向下搜
    }
    else //同理
    {
        if(t <= Node[k*2+1].l + Node[k*2+1].lq - 1)
        {
            ans += (Node[k*2+1].lq + Node[k*2].rq);
            return;
        }
        else
            qinter(k*2+1, t);
    }
}

int main()
{
    int n, m;
    ans = 0;
   while(~scanf("%d%d",&n,&m)){
        build(1, 1, n);
        stack<int> G;
        getchar();
        for(int i=0; i<m; i++)
        {
            char str[1010];
            scanf("%s",str);
            if(strcmp(str, "D") == 0)
            {
                scanf("%d",&x);
                G.push(x);
                y = 0;
                chp(1);
            }
            else if(strcmp(str, "R") == 0)
            {
                x = G.top();
                G.pop();
                y = 1;
                chp(1);
            }
            else if(strcmp(str, "Q") == 0)
            {
                scanf("%d",&x);
                ans = 0;
                qinter(1, x);
                printf("%d
",ans);
            }

        }
   }
    return 0;
}

 

以上是关于Tunnel Warfare HDU - 1540(线段树最长连续区间)的主要内容,如果未能解决你的问题,请参考以下文章

HDU1540 Tunnel Warfare —— 线段树 区间合并

hdu1540 Tunnel Warfare

hdu1540 Tunnel Warfare 线段树/树状数组

hdu--1540 Tunnel Warfare(线段树+区间合并)

线段树区间合并HDU1540-Tunnel Warfare

HDU 1540 Tunnel Warfare(线段树,单点更新,区间查询)