hdu1540 Tunnel Warfare--单点更新查询 & 区间合并

原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=1540


题意:

一条直线,n个点,标号1-----n,m个操作,规则如下:

D x :摧毁点x

Q x  :查询包含点x的最长序列

R : 恢复上一次被摧毁的一个点

思路就是:我们把所有点初始为1,摧毁该点就赋值为0,用栈保存摧毁的点,当需要恢复时就取出栈顶,进行更新。


#define _CRT_SECURE_NO_DEPRECATE 

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int s[50005];//模拟栈,把删除的数放进去,待rebuild的时候取出
int top;

struct Node
{
	int l, r, mid;
	int len;
	int lsum, rsum, msum;
}p[50005 * 4];

void pushUp(int n)
{
	p[n].lsum = p[n * 2].lsum + (p[n * 2].lsum == p[n * 2].len ? p[n * 2 + 1].lsum : 0);
	p[n].rsum = p[n * 2 + 1].rsum + (p[n * 2 + 1].rsum == p[n * 2 + 1].len ? p[n * 2].rsum : 0);
	p[n].msum = max(max(p[n * 2].msum, p[n * 2 + 1].msum), p[n * 2].rsum + p[n * 2 + 1].lsum);
}

void build(int n, int l, int r)
{
	p[n].l = l;
	p[n].r = r;
	p[n].mid = (l + r) / 2;
	p[n].len = r - l + 1;
	p[n].lsum = p[n].rsum = p[n].msum = p[n].len;
	if (l == r)
		return;

	build(n * 2, l, p[n].mid);
	build(n * 2 + 1, p[n].mid + 1, r);
}

void update(int n, int pos, int c)
{
	if (p[n].l == p[n].r)
	{
		if (c == 1)
			p[n].lsum = p[n].rsum = p[n].msum = 1;//rebuild
		else
			p[n].lsum = p[n].rsum = p[n].msum = 0;//destroy

		return;//要return,害死人啊
	}

	if (pos <= p[n].mid)
		update(n * 2, pos, c);
	else
		update(n * 2 + 1, pos, c);

	pushUp(n);
}

int query(int n, int pos)
{
	if (p[n].l == p[n].r || p[n].msum == p[n].len || p[n].msum == 0)//到了叶子节点或者该访问区间为空或者已满都不必要往下走了  
		return p[n].msum;

	if (pos <= p[n].mid)
	{
		if (pos >= p[n * 2].r - p[n * 2].rsum + 1)
			return p[n * 2].rsum + p[n * 2 + 1].lsum;
		else
			return query(n * 2, pos);
	}
	else
	{
		if (pos <= p[n * 2 + 1].l + p[n * 2 + 1].lsum - 1)
			return p[n * 2].rsum + p[n * 2 + 1].lsum;
		else
			return query(n * 2 + 1, pos);
	}
}

int main()
{
	char ch[5];
	int n, m;
	int pos;
	while (~scanf("%d%d", &n, &m))
	{
		top = 0;

		build(1, 1, n);

		while (m--)
		{
			scanf("%s", ch);

			if (ch[0] == 'D')
			{
				scanf("%d", &pos);
				s[top++] = pos;
				update(1, pos, 0);//0代表destroy
			}
			else if (ch[0] == 'Q')
			{
				scanf("%d", &pos);
				printf("%d\n", query(1, pos));
			}
			else
			{
				if (top > 0)//栈还有数的话,注意这里要判断
				{
					pos = s[--top];
					update(1, pos, 1);//1代表rebuild
				}
			}
		}
	}

	return 0;
}






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值