Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 7367    Accepted Submission(s): 2870

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
 
Source
 

【题解】

这题为求某个区间从最右往左(或从左往右)的连续序列提供了一个很好的思路。

具体的;

我们这道题的有没有被损坏可以构成一个01串。

然后我们用线段树的域来存储从最左端开始往右的连续的1的个数以及从最右端开始往左的连续的1的个数;

分别表示为llx[rt],rlx[rt];

在建树的时候可以维护一个序列全部为1的llx,rlx的信息;

然后单节点的操作也没问题,操作完修改就好了。

然后就是求一个位置x它所在的连续块的长度。

可以这样。

求1..x-1中从x-1往左连续的1的个数。

求x+1..n中从x+1往右连续的1的个数。

然后加上本身就好。

实现的方法很巧妙。自己看代码吧。

然后说一下。

这题hdu上是多组数据。

然后会重复出现某个村庄x。即x被多次损坏。

但只要修一次就能好。

但是如果你修好了x。栈中又出现了一次x。而你恰好要进行R操作。

那么你不能跳过这个x。虽然它已经修好了。但是还是要消耗一个R操作。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#define lson begin,m,rt<<1
#define rson m+1,end,rt<<1|1 using namespace std; const int MAXN = 51000; int n, m;
int llx[MAXN * 4],rlx[MAXN*4],stack[MAXN*2],top;
bool lph[MAXN*4],rph[MAXN*4],huihuai[MAXN]; void push_up(int rt,int len) //合并区间要用到节点所代表的区间的长度。
{
llx[rt] = llx[rt << 1];
if (llx[rt] == (len - (len >> 1)))
llx[rt] += llx[rt << 1 | 1];
rlx[rt] = rlx[rt << 1 | 1];
if (rlx[rt] == (len >> 1))
rlx[rt] += rlx[rt << 1];
lph[rt] = lph[rt << 1];
rph[rt] = rph[rt << 1 | 1];
} void build(int begin, int end, int rt)
{
if (begin == end)
{
lph[rt] = rph[rt] = false;
llx[rt] = rlx[rt] = 1;
return;
}
int m = (begin + end) >> 1;
build(lson);
build(rson);
push_up(rt,end-begin+1);
} void up_data(int pos, int num,int begin, int end, int rt) //把某个点修好或毁坏
{
if (begin == end)
{
if (num == 1)
{
lph[rt] = rph[rt] = true;
llx[rt] = rlx[rt] = 0;
}
else
{
lph[rt] = rph[rt] = false;
llx[rt] = rlx[rt] = 1;
}
return;
}
int m = (begin + end) >> 1;
if (pos <= m)
up_data(pos, num, lson);
else
up_data(pos, num, rson);
push_up(rt, end - begin+1);
} int query_left(int l, int r, int begin, int end, int rt)//这是1..x-1中从x-1往左的连续的1的个数
{
if (l <= begin && end <= r)
return rlx[rt];
int m = (begin + end) >> 1;
if (r <= m)
return query_left(l, r, lson);
else
if (m < l)
return query_left(l, r, rson);
else
{
int temp1 = query_left(l, m, lson); //注意所求区间发生了改变。
int temp2 = query_left(m+1, r, rson);
if (r - m == temp2) //如果整个(m+1..r)都是连续的1则可以加上左半部分
return temp1 + temp2;
return temp2;
} } int query_right(int l, int r, int begin, int end, int rt)
{
if (l <= begin && end <= r)
return llx[rt];
int m = (begin + end) >> 1;
if (r <= m)
return query_right(l, r, lson);
else
if (m < l)
return query_right(l, r, rson);
else
{
int temp1 = query_right(l, m, lson);
int temp2 = query_right(m + 1, r, rson);
if (m - l + 1 == temp1)
return temp1 + temp2;
return temp1;
}
} void output_ans()
{
for (int i = 1; i <= m; i++)
{
char op[10];
int x;
scanf("%s", op);
if (op[0] == 'D')
{
scanf("%d", &x);
up_data(x, 1, 1, n, 1);
huihuai[x] = true;
top++;
stack[top] = x;
}
else
if (op[0] == 'R')
{
if (top > 0)
{
if (huihuai[stack[top]])
{
huihuai[stack[top]] = false;
up_data(stack[top], 0, 1, n, 1);
top--;
}
}
}
else
if (op[0] == 'Q')
{
scanf("%d", &x);
if (huihuai[x])
printf("0\n");
else
{
int sum1 = 0, sum2 = 0;
if (x >= 2)
sum1 = query_left(1, x - 1, 1, n, 1);
if (x <= n - 1)
sum2 = query_right(x + 1, n, 1, n, 1);
if (!huihuai[x])
sum2++;
printf("%d\n", sum1 + sum2);
}
}
}
} void init()
{
memset(huihuai, false, sizeof(huihuai));
memset(stack, 0, sizeof(stack));
top = 0;
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
//freopen("F:\\rush_out.txt", "w", stdout);
while (scanf("%d%d", &n, &m) != EOF)
{
init();
build(1, n, 1);
output_ans();
}
return 0; }

【38.96%】【hdu 1540】Tunnel Warfare的更多相关文章

  1. 【改革春风吹满地 HDU - 2036 】【计算几何-----利用叉积计算多边形的面积】

    利用叉积计算多边形的面积 我们都知道计算三角形的面积时可以用两个邻边对应向量积(叉积)的绝对值的一半表示,那么同样,对于多边形,我们可以以多边形上的一个点为源点,作过该点并且过多边形其他点中的某一个的 ...

  2. hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】

    Tunnel Warfare                                                             Time Limit: 4000/2000 MS ...

  3. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  4. 【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间 ...

  5. 【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5491 题目大意: 一个数D(0<=D<231),求比D大的第一个满足:二进制下1个个数在 ...

  6. 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...

  7. 【动态规划】【KMP】HDU 5763 Another Meaning

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成 ...

  8. 【归并排序】【逆序数】HDU 5775 Bubble Sort

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 题目大意: 冒泡排序的规则如下,一开始给定1~n的一个排列,求每个数字在排序过程中出现的最远端 ...

  9. 【中国剩余定理】【容斥原理】【快速乘法】【数论】HDU 5768 Lucky7

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5768 题目大意: T组数据,求L~R中满足:1.是7的倍数,2.对n个素数有 %pi!=ai  的数 ...

随机推荐

  1. js不停地触发按钮的事件

    例子:不断地发匿名邮件 http://tool.chacuo.net/mailsend 在控制台写:setInterval('$(".convert :input[arg]").t ...

  2. HDU 4217

    点击打开题目链接 题型就是数据结构.给一个数组,然后又k次操作,每次操作给定一个数ki, 从数组中删除第ki小的数,要求的是k次操作之后被删除的所有的数字的和. 简单的思路就是,用1标记该数没有被删除 ...

  3. [React Native]Promise机制

    React Native中经常会看到Promise机制. Promise机制代表着在JavaScript程序中下一个伟大的范式.可以把一些复杂的代码轻松撸成一个串,和Android中的rxjava非常 ...

  4. Python学习之路2☞数据类型与变量

    变量 变量作用:保存状态:说白了,程序运行的状态就是状态的变化,变量是用来保存状态的,变量值的不断变化就产生了运行程序的最终输出结果 一:声明变量 #!/usr/bin/env python # -* ...

  5. jQuery 鼠标移入图片 显示大图并跟随鼠标移动

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. Centos7环境下搭建Nginx+Lua+Redis进行数据存取

    1.安装依赖环境 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.安装LuaJIT cd /usr/loca ...

  7. hdu 1003 hdu 1231 最大连续子序列【dp】

    HDU1003 HDU1231 题意自明.可能是真的进步了点,记得刚开始研究这个问题时还想了好长时间,hdu 1231还手推了很长时间,今天重新写干净利落就AC了. #include<iostr ...

  8. python 内置函数补充 or 递归 or 二分法

    一.内置函数的补充 repr() 显示出字符串的官方表示形式 chr() print(chr(20013)) # 把数字编码转换成字符串 ord() print(ord('中')) # 20013 把 ...

  9. Java练习 SDUT-1194_余弦

    C语言实验--余弦 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入n的值,计算cos(x). Input 输入数据 ...

  10. react+antd 点击分页为上次操作结果

    最近项目中在使用antd的分页组件时发生了第一次点击分页无变化,再次点击时数据为上一次的分页结果,代码如下: setPageIndex = (pagination)=> { const page ...