zoukankan      html  css  js  c++  java
  • 【38.96%】【hdu 1540】Tunnel Warfare

    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
    ");
    					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
    ", 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;
    
    }


  • 相关阅读:
    ubuntu: no module named _sqlite
    mysql慢查询分析工具 pt-query-digest
    vue中的时间修饰符stop,self
    面试题 —— Ajax的基本原理总结
    es6笔记 day6-Symbol & generator
    类(class)和继承
    es6笔记 day4---模块化
    es6笔记 day3---Promise
    es6笔记 day3---对象简介语法以及对象新增
    es6笔记 day3---数组新增东西
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632259.html
Copyright © 2011-2022 走看看