http://acm.hdu.edu.cn/showproblem.php?pid=1540

题目大意:抗日战争期间进行地道战,存在n个村庄用地道连接,输入D表示破坏某个村庄(摧毁与其相连的地道, 包括其本身),输入R表示重建最后被破坏的那个村庄。

输入Q表示查询某村庄可通过地道到达多少个村庄(包含本身)。

将题目理想化,即为找与某点直接或间接相连的有多少个点。即通过此点的线段的最大长度。当此点时破坏时默认为0.抽象为此过程后发现即为在线段上执行的操作,即线

段树知识点。分析:此点可能为孤立(0), 可能位于某线段左区间的线段,可能位于某线段右区间的线段,可能为左右区间都经过的线段。故在线段树种定义lsum表示此

区间左端向右可到达的极限长度,rsum表示此区间从右端向左可达到的极限长度, sum表示此区间内的最大长度。分析更新,注意细节即可。

#include <stdio.h>
#include <stack>
#include <algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
#define N 100005
struct tree
{
    int l, r, lsum, rsum, sum;
    int mid()
    {
        return (l+r)/2;
    }
    int len()
    {
        return (r-l+1);
    }
}a[N<<2];
void build(int rt, int l, int r)
{
    a[rt].l = l;
    a[rt].r = r;
    a[rt].lsum = a[rt].rsum = a[rt].sum = a[rt].len();
    if(l==r)return ;
    build(lson, l, a[rt].mid());
    build(rson, a[rt].mid()+1, r);
}
void Combine(int rt)
{
    a[rt].lsum = a[lson].lsum;
    a[rt].rsum = a[rson].rsum;

if(a[lson].lsum == a[lson].len())///左儿子的左极限为全区间,则说明可以与右区间合并
        a[rt].lsum += a[rson].lsum;
    if(a[rson].rsum == a[rson].len())
        a[rt].rsum += a[lson].rsum;

a[rt].sum = max(max(a[rt].lsum, a[rt].rsum), a[lson].rsum+a[rson].lsum);
}
void Destroy(int rt, int k, int e)
{
    if(a[rt].l==a[rt].r)
    {
        a[rt].lsum = a[rt].rsum = a[rt].sum = e;
        return ;
    }
    if(a[rt].mid()>=k)Destroy(lson, k, e);
    else Destroy(rson, k, e);

Combine(rt);
}
int Query(int rt, int k)
{
    if(a[rt].sum == 0)return 0;///在点上
    if(k<a[rt].l+a[rt].lsum)return a[rt].lsum;///在线段中;
    if(k>a[rt].r-a[rt].rsum)return a[rt].rsum;
    if(k>a[lson].r-a[lson].rsum && k<a[rson].lsum+a[rson].l)
        return a[lson].rsum + a[rson].lsum;

if(a[rt].mid()>=k)return Query(lson, k);
    else return Query(rson, k);
}
int main()
{
    int m, n;
    while(scanf("%d %d", &n, &m)!=EOF)
    {
        build(1, 1, n);
        char order[10];
        int x;
        stack<int>Q;
        while(m--)
        {
            scanf("%s", order);
            if(order[0]=='D')
            {
                scanf("%d", &x);
                Q.push(x);
                Destroy(1, x, 0);
            }
            else if(order[0]=='R' && Q.size())
            {
                x = Q.top();
                Q.pop();
                Destroy(1, x, 1);
            }
            else
            {
                scanf("%d", &x);
                printf("%d\n", Query(1, x));
            }
        }
    }
    return 0;
}

HDU 1540 Tunnel Warfare(线段树+区间合并)的更多相关文章

  1. HDU 1540 Tunnel Warfare 线段树区间合并

    Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...

  2. hdu 1540 Tunnel Warfare 线段树 区间合并

    题意: 三个操作符 D x:摧毁第x个隧道 R x:修复上一个被摧毁的隧道,将摧毁的隧道入栈,修复就出栈 Q x:查询x所在的最长未摧毁隧道的区间长度. 1.如果当前区间全是未摧毁隧道,返回长度 2. ...

  3. hdu 1540 Tunnel Warfare(线段树区间统计)

    Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

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

    Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  5. Tunnel Warfare 线段树 区间合并|最大最小值

    B - Tunnel WarfareHDU - 1540 这个有两种方法,一个是区间和并,这个我个人感觉异常恶心 第二种方法就是找最大最小值 kuangbin——线段树专题 H - Tunnel Wa ...

  6. HDU 1540 Tunnel Warfare (线段树)

    Tunnel Warfare Problem Description During the War of Resistance Against Japan, tunnel warfare was ca ...

  7. HDU 1540 Tunnel Warfare (线段树)

    题目大意: n 个村庄排列在一条直线上,相邻的村庄有地道连接,除首尾两个村庄外,其余村庄都有两个相邻的村庄.其中有 3 中操作 D x :表示摧毁编号为 x 的村庄,Q x:表示求出包含村庄 x 的最 ...

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

    题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. 析:首先可以用set水过,set用来记录每个被破坏的村庄,然后查找时,只要查找左右两个端点好. 用线段 ...

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

    题目链接:https://vjudge.net/problem/HDU-1540 uring the War of Resistance Against Japan, tunnel warfare w ...

  10. HDU 6638 - Snowy Smile 线段树区间合并+暴力枚举

    HDU 6638 - Snowy Smile 题意 给你\(n\)个点的坐标\((x,\ y)\)和对应的权值\(w\),让你找到一个矩形,使这个矩阵里面点的权值总和最大. 思路 先离散化纵坐标\(y ...

随机推荐

  1. [转]Dll注入经典方法完整版

    Pnig0s1992:算是复习了,最经典的教科书式的Dll注入. 总结一下基本的注入过程,分注入和卸载 注入Dll: 1,OpenProcess获得要注入进程的句柄 2,VirtualAllocEx在 ...

  2. zookeeper安装及部署

    安装及部署 一. 单机安装.配置 1.下载zookeeper二进制安装包 下载 curl -L -O http://apache.fayea.com/zookeeper/stable/zookeepe ...

  3. 【freemaker】之判断是否为空,表达式的使用

    测试代码 @Test public void test05(){ try { freemakerUtil.fprint(root, "05.ftl",fn+"05.htm ...

  4. (C#) Tasks 中的异常处理(Exception Handling.)

    多线程编程中要注意对线程异常的处理.首先写个例子. 一个线程用于显示信息(Show Messages).主线程用于做其他工作(Do Works). using (Task taskShowMessag ...

  5. loadView、viewDidLoad、initWithCoder、initWithNibName、awakeFromNib的用法

    转载,原地址为:http://jianyu996.blog.163.com/blog/static/11211455520131226840879/ 请尊重原创: 1,无论XIB还是代码创建都会调用l ...

  6. NeHe OpenGL教程 第四十六课:全屏反走样

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. 2 、Linux基本命令-ls-pwd-cd-date-hwclock

    Linux基本命令: 1.ls-查看目录下的文档 语法: ls 目录 注: .当前目录  ..上级目录 如:ls /etc/ 相关参数: -l  显示详细信息 ls /etc/ -l -a 显示隐藏的 ...

  8. SESSION和COOKIE的作用和区别,SESSION信息的存储方式,如何进行遍历?

    二者的定义:当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择,都纪录下来.当下次你再光临同一个网站,WEB 服务器会先看看有没有 ...

  9. Mobile Web调试工具Weinre (reproduce)

    Mobile Web调试工具Weinre 现在.将来,用移动设备上网越来越成为主流.但对于开发者们来说,移动web的调试一直是个难题,前期可以使用模拟器来协助调试,但到了真机调试阶段就让人非常头痛.而 ...

  10. (转)DataGridView多维表头及其扩展功能

    dataGridView1.RowHeadersVisible = false;把整行选中那一列去掉.如果需要整行选中,新增一按钮列模拟实现.上源码:多维DataGridView 有个简易的方法: 1 ...