【线段树区间合并】HDU1540-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 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的更多相关文章
- Tunnel Warfare(HDU1540+线段树+区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- HYSBZ 1858 线段树 区间合并
//Accepted 14560 KB 1532 ms //线段树 区间合并 /* 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[ ...
- poj3667 线段树 区间合并
//Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- hdu3911 线段树 区间合并
//Accepted 3911 750MS 9872K //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...
- 线段树(区间合并) POJ 3667 Hotel
题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...
随机推荐
- sql条件为空查询全部,不为空按条件查询以及多条件筛选查询。
procedure queryLackLonOrLatTdCell(i_region_name varchar2, i_state varchar2) is begin select region_n ...
- iOS:使用模板引擎渲染HTML界面
在实际开发中,UIWebView控件接受一个HTML内容,用于相应的界面,下面是该API的接口: - (void)loadHTMLString:(NSString *)string baseURL:( ...
- Windows Server 2008 R2 组策略基本设置
域控组策略基本设置 标注: 组策略计算配置:系统需要重启才生效 组策略用户配置:系统注销即可生效 一. 域用户登录桌面后自动 ...
- jQuery源代码学习之九—jQuery事件模块
jQuery事件系统并没有将事件坚挺函数直接绑定在DOM元素上,而是基于事件缓存模块来管理监听函数的. 二.jQuery事件模块的代码结构 //定义了一些正则 // // //jQuery事件对象 j ...
- lua协程一则报错解决“attempt to yield across metamethod/C-call boundary”
问题 attempt to yield across metamethod/C-call boundary 需求跟如下帖子中描述一致: http://bbs.chinaunix.net/forum.p ...
- querystring 解析url 查询字符串
对前端同学来说,经常要碰到一种比较麻烦的情况,那就是url查询字符串的解析问题.说起来也不难,就是比较麻烦. 具体来处理这种情况的时候,相信有一部分同学就是针对具体项目中的需要的字符去正则匹配一下,业 ...
- c++实验,需要的人都知道是啥
利用点.线.面的基本知识,声明Point,Line,Friangle,PolyAngle四个类,完成以下功能.Point类功能://实验88888(1) 移动一个点:(2) 显示一个点:(3) 可计算 ...
- Navicat Premium相关注册码
--Navicat for SQL Server V10.0.10NAVD-3CG2-6KRN-IEPMNAVL-NIGY-6MYY-XWQENAVI-C3UU-AAGI-57FW --Navicat ...
- Spring配置AOP实现定义切入点和织入增强
XML里的id=””记得全小写 经过AOP的配置后,可以切入日志功能.访问切入.事务管理.性能监测等功能. 首先实现这个织入增强需要的jar包,除了常用的 com.springsource.org.a ...
- 随手编程---快速排序(QuickSort)-Java实现
背景 快速排序,是在上世纪60年代,由美国人东尼·霍尔提出的一种排序方法.这种排序方式,在当时已经是非常快的一种排序了.因此在命名上,才将之称为"快速排序".这个算法是二十世纪的七 ...