一、题目

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 directly connected with two neighboring ones.

Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!

Input

The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.

There are three different events described in different format shown below:

D x: The x-th village was destroyed.

Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.

R: The village destroyed last was rebuilt.

Output

Output the answer to each of the Army commanders’ request in order on a separate line.

Sample Input

7 9

D 3

D 6

D 5

Q 4

Q 5

R

Q 4

R

Q 4

Sample Output

1

0

2

4

顺便附上原题链接→_→Problem-1540

二、题目分析

和普通的线段树没什么太大差别,只是每个区间加了两个变量——lsum和rsum,分别表示这个区间左起向右连续“1”串的长度和右起向左连续“1”串的长度。在维护树回溯时,一个区间的lsum等于其左区间的lsum,rsum等于其右区间的rsum。特别的,当一个区间左区间的lsum等于其左区间长度,即该区间左区间是一个连续的“1”串时,该区间lsum需额外加上其右区间的lsum;对于其rsum同理。

三、代码实现

这题有个天坑,题目完全没提到,但这题有多组数据_(:з」∠)_

 #include<cstdio>
#include<cstring>
const int MAXN=5e4+;
int n,m;
struct node
{
int l,r;
int lsum,rsum;
}tr[MAXN<<];
int stack[MAXN],top;
void build(int x,int y,int i)
{
tr[i].l=x,tr[i].r=y;
if(x==y)
{
tr[i].lsum=;
tr[i].rsum=;
return;
}
int mid=(tr[i].l+tr[i].r)>>;
build(x,mid,i<<);
build(mid+,y,i<<|);
tr[i].lsum=y-x+,tr[i].rsum=y-x+;
return;
}
void update(int x,int i,int val)
{
if(tr[i].l==x&&tr[i].r==x)
{
tr[i].lsum=val;
tr[i].rsum=val;
return;
}
int mid=(tr[i].l+tr[i].r)>>;
if(x<=mid)
{
update(x,i<<,val); }
else
{
update(x,i<<|,val);
}
tr[i].lsum=tr[i<<].lsum;
tr[i].rsum=tr[i<<|].rsum;
if(tr[i<<].lsum==tr[i<<].r-tr[i<<].l+)tr[i].lsum+=tr[i<<|].lsum;
if(tr[i<<|].rsum==tr[i<<|].r-tr[i<<|].l+)tr[i].rsum+=tr[i<<].rsum;
}
int query_left(int x,int i)
{
if(tr[i].r==x)
{
if(tr[i].rsum==tr[i].r-tr[i].l+&&tr[i].l!=)
{
return tr[i].rsum+query_left(tr[i].l-,);
}
return tr[i].rsum;
}
int mid=(tr[i].l+tr[i].r)>>;
if(x<=mid)
{
return query_left(x,i<<);
}
else
{
return query_left(x,i<<|);
}
}
int query_right(int x,int i)
{ if(tr[i].l==x)
{
if(tr[i].lsum==tr[i].r-tr[i].l+&&tr[i].r!=n)
{
return tr[i].lsum+query_right(tr[i].r+,);
}
return tr[i].lsum;
}
int mid=(tr[i].l+tr[i].r)>>;
if(x<=mid)
{
return query_right(x,i<<);
}
else
{
return query_right(x,i<<|);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(tr,,sizeof(tr));
memset(stack,,sizeof(stack));
top=;
build(,n,);
for(int i=;i<=m;++i)
{
char c;
int x;
scanf("\n%c",&c);
if(c=='D')
{
scanf("%d",&x);
stack[++top]=x;
update(x,,);
}
else if(c=='R')
{
update(stack[top--],,);
}
else
{
scanf("%d",&x);
int ans=query_left(x,)+query_right(x,)-;
if(ans<=)printf("0\n");
else printf("%d\n",ans);
}
}
}
return ;
}

HDU1540-Tunnel Warfare

弱弱地说一句,本蒟蒻码字也不容易,转载请注明出处http://www.cnblogs.com/Maki-Nishikino/p/6230606.html

【线段树区间合并】HDU1540-Tunnel Warfare的更多相关文章

  1. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  2. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  3. HDU 3911 线段树区间合并、异或取反操作

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...

  4. HDU 3911 Black And White(线段树区间合并+lazy操作)

    开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...

  5. HYSBZ 1858 线段树 区间合并

    //Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...

  6. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  7. hdu3911 线段树 区间合并

    //Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  8. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  9. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

随机推荐

  1. Java语言程序设计(基础篇) 第六章 方法

    第六章 方法 6.2 定义方法 1.方法的定义由方法名称.参数.返回值类型以及方法体组成. 2.定义在方法头中的变量称为形式参数(formal parameter)或者简称为形参(parameter) ...

  2. Unity 编译apk启动出异常

    问题:unity 编译出来的apk,在android安装启动,时报以下错误: 07-06 20:52:48.282: E/linker(18229): load_library(linker.cpp: ...

  3. (转载)Resin安装配置及使用教程

    Resin是一个提供高性能的,支持 Java/PHP 的应用服务器.目前有两个版本:一个是GPL下的开源版本,提供给一些爱好者.开发人员和低流量网站使用:一种是收费的专业版本,增加了一些更加适用于生产 ...

  4. T4

    Text Template Transformation Toolkit T4语法感觉有点像aspx的视图模板<% %>. 使用可以通过VS扩展和更新安装"T4 Toolbox ...

  5. 百度地图坐标纠偏和转换工具和DLL

    百度一直以来都是个即想装出一副拥抱互联网开放的样子,又为了短期商业利益封闭自己的公司,模仿谷歌地图,开放了自己的百度地图 API,为了防止别人盗用其数据和用户自由迁移,地图相比于火星坐标,又更加封闭, ...

  6. Spring

    Spring 一个支持DI/IOC和AOP的开源容器框架 特点 DI/IOC DI 依赖注入(组件以特定方式接收来自容器的资源注入) IOC 控制反转(反转资源获取的方向) AOP 面向切面编程 开发 ...

  7. OEIS A140358

    以前也许做过? 有点方 最小整数1到k 加减得到 n 1+-2+-3+-...+-k = n 求最小k #include <cstdio> #include <algorithm&g ...

  8. Android开源图表之树状图和饼状图的官方示例的整理

    最近由于工作需要,所以就在github上搜了下关于chart的三方框架 官方地址https://github.com/PhilJay/MPAndroidChart 由于工作需要我这里整理了一份Ecli ...

  9. LED将为我闪烁:控制发光二极管

      一个完整的linux驱动主要由内部处理和与硬件交互两部分组成.其中内部处理主要是指linux驱动的装载.卸载.与设备文件相关的动作处理以及业务逻辑等:与硬件交互主要是指通过iowrite32.io ...

  10. 怎么在js中,访问viewbag,viewdata等等的值

    在js中要访问viewbag,viewdata存储的值, var ss='@ViewBag.name'; 一定要加引号,单双随便,还有, ViewBag一定要写规范,不然会编译错误! 成功者的秘诀就是 ...