Tunnel Warfare

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3318    Accepted Submission(s): 1280

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 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

分析:设置lsum[n],rsum[n]分别表示区间左端连续村庄个数,区间右端连续村庄个数

查询的时候只要查询1~a右端连续个数+a~n左端连续个数,如果大于0就输出个数-1(因为a算了两次)

写完百度了下别人的代码,发现别人写的线段树和自己写的不怎么一样,于是就想学学,奈何。。。实在是不愿意看别人的代码,特别是那些没格式的还比较乱的。。。自己太懒了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iomanip>
#define INF 99999999
using namespace std; const int MAX=50000+10;
int lsum[MAX<<2],rsum[MAX<<2];//分别记录区间内最大连续村庄,左端最大连续村庄,右端最大连续村庄
int s[MAX],size,n,m,a;//s记录破坏的村庄编号
char ch[2];
bool mark[MAX];//mark标记村庄是否破坏,0表示没破坏,1表示破坏 void Upfather(int n,int m){//更新区间左右端连续村庄个数
lsum[n]=lsum[n<<1];
rsum[n]=rsum[n<<1|1];
if(lsum[n] == m-(m>>1))lsum[n]+=lsum[n<<1|1];
if(rsum[n] == m>>1)rsum[n]+=rsum[n<<1];
} void BuildTree(int left,int right,int n){
lsum[n]=rsum[n]=right-left+1;
if(left == right)return;
int mid=left+right>>1;
BuildTree(left,mid,n<<1);
BuildTree(mid+1,right,n<<1|1);
} void Update(int p,int date,int left,int right,int n){
if(left == right){lsum[n]=(rsum[n]+=date);return;}
int mid=left+right>>1;
if(p<=mid)Update(p,date,left,mid,n<<1);
else Update(p,date,mid+1,right,n<<1|1);
Upfather(n,right-left+1);
} int QueryL(int L,int R,int left,int right,int n){//查询a~n的左端连续村庄个数
if(L<=left && right<=R)return lsum[n];
int mid=left+right>>1,lans,rans;
if(L<=mid)lans=QueryL(L,R,left,mid,n<<1);
if(R>mid)rans=QueryL(L,R,mid+1,right,n<<1|1);
if(R<=mid)return lans;
if(L>mid)return rans;
if(lans == mid-L+1)return lans+rans;
return lans;
}
/*另一种写法或许更好理解
int QueryL(int L,int R,int left,int right,int n){
if(L<=left && right<=R)return lsum[n];
int mid=left+right>>1,lans,rans;
if(R<=mid)return QueryL(L,R,left,mid,n<<1);
else if(L>mid)return QueryL(L,R,mid+1,right,n<<1|1);
else{
lans=QueryL(L,mid,left,mid,n<<1);
rans=QueryL(mid+1,R,mid+1,right,n<<1|1);
if(lans == mid-L+1)return lans+rans;
return lans;
}
}
*/ int QueryR(int L,int R,int left,int right,int n){//查询1~a右端村庄连续个数
if(L<=left && right<=R)return rsum[n];
int mid=left+right>>1,lans,rans;
if(L<=mid)lans=QueryR(L,R,left,mid,n<<1);
if(R>mid)rans=QueryR(L,R,mid+1,right,n<<1|1);
if(R<=mid)return lans;
if(L>mid)return rans;
if(rans == R-mid)return lans+rans;
return rans;
}
/*另一种写法或许更好理解
int QueryR(int L,int R,int left,int right,int n){
if(L<=left && right<=R)return rsum[n];
int mid=left+right>>1,lans,rans;
if(R<=mid)return QueryR(L,R,left,mid,n<<1);
else if(L>mid)return QueryR(L,R,mid+1,right,n<<1|1);
else{
lans=QueryR(L,mid,left,mid,n<<1);
rans=QueryR(mid+1,R,mid+1,right,n<<1|1);
if(rans == R-mid)return lans+rans;
return rans;
}
}
*/ int main(){
while(~scanf("%d%d",&n,&m)){
BuildTree(1,n,1);
size=0;
memset(mark,false,sizeof(bool)*(n+2));
mark[0]=true;
for(int i=0;i<m;++i){
scanf("%s",ch);
if(ch[0] == 'D'){
scanf("%d",&a);
s[++size]=a;
if(!mark[a])Update(a,-1,1,n,1),mark[a]=true;
}else if(ch[0] == 'R'){
while(!mark[s[size]])--size;//已经被修复过了就修复下一个,比如3 2 2,第一次修复2,现在修复3而不是2
if(size)Update(s[size],1,1,n,1),mark[s[size--]]=false;
}else{
scanf("%d",&a);
int temp=QueryL(a,n,1,n,1)+QueryR(1,a,1,n,1);
printf("%d\n",temp>0?temp-1:0);
}
}
}
return 0;
}

hdu1540之线段树单点更新+区间合并的更多相关文章

  1. POJ 2892 Tunnel Warfare(线段树单点更新区间合并)

    Tunnel Warfare Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7876   Accepted: 3259 D ...

  2. HDU 3308 LCIS(线段树单点更新区间合并)

    LCIS Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting ...

  3. hdu 5316 Magician(2015多校第三场第1题)线段树单点更新+区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316 题意:给你n个点,m个操作,每次操作有3个整数t,a,b,t表示操作类型,当t=1时讲a点的值改 ...

  4. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  5. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

  6. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  7. hdu 1166线段树 单点更新 区间求和

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  8. hdu1166(线段树单点更新&区间求和模板)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:中文题诶- 思路:线段树单点更新,区间求和模板 代码: #include <iost ...

  9. hdu2795(线段树单点更新&区间最值)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一个 h * w 的板子,要在上面贴 n 条 1 * x 的广告,在贴第 i 条广告时要 ...

随机推荐

  1. HDU 2104 hide handkerchief

    题解:由题目可以知道,如果n和m的最大公约数不为1,那么总有箱子是无法遍历的,所以求一遍GCD就可以判断了. 注意点:一定要记住判断是==,在做题时又忘了. #include <cstdio&g ...

  2. C++模板:字典树

    //插入 void insert(char *s,char *s1){ for(int l=strlen(s),x=0,i=0;i<l;i++){ if(!trie[x].son[s[i]-'a ...

  3. Linux 下的多线程编程

    随着你对编程的深入,多线程是一个免不了的话题,在这里就对多线程做一个比较详细的总结. 首先摆在我们面前的就是什么是线程,以及为么会有这个东西.记得之前学习的时候自己会画一张很大的图,在图中可以详细的写 ...

  4. Qtwebkit配置,设置交叉编译环境 - croop520的专栏 - 博客频道 - CSDN.NET

    Qtwebkit配置,设置交叉编译环境 - croop520的专栏 - 博客频道 - CSDN.NET Qtwebkit配置,设置交叉编译环境 分类: Qt Webkit 2012-04-12 15: ...

  5. Objective-C浅拷贝和深拷贝

    浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间 如: char* str = (char*)malloc(100);char* str2 = str; 浅拷贝只是对对象的简单拷贝 ...

  6. Memcached源代码分析 - Memcached源代码分析之消息回应(3)

    文章列表: <Memcached源代码分析 - Memcached源代码分析之基于Libevent的网络模型(1)> <Memcached源代码分析 - Memcached源代码分析 ...

  7. android程序报错“error launching activity com.android.ddmlib.shellcommandunresponsiveexception”的解决方式

    今天在调试android程序的时候,因为是NDK开发,要先编译.so库再打包下载到android模拟器,所以花费的时间比較长.控制台就会报例如以下错误: error launching activit ...

  8. android service和activity的通讯

    我们须要用下面方式来启动service: </pre><pre name="code" class="java"><span st ...

  9. 通知/代理/block 三者比对

    通知 :   “一对多”,”多对一” 传值 四个步骤:  1.发送通知2.创建监听者3.接收通知4.移除监听者 使用场景:1- 很多控制器都需要知道一个事件,应该用通知:2 - 相隔多层的两个控制器之 ...

  10. 玩转Bootstarp(连载)

    一.Bootstarp是什么? 简单.灵活的用于搭建WEB页面的HTML.CSS.JS的工具集 (基于HTML5和CSS3) 总结:简洁强大的前端开发框架,可以让WEB开发更迅速.更简单 二.如何使用 ...