C - Tunnel Warfare (HDU - 1540)

- 题目大意

    D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少,然后根据命令来进行模拟操作。

- 解题思路

  这个我是根据线段树的区间合并的模板来写的,用三个变量记录左边连续区间,右边连续区间和最大连续区间,用栈来存储点(修复的时候要用),其余的就是更新点,然后查询最大的连续区间。

- 代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 50001;
struct node
{
	int l, r;
	int ls, rs, ms;
}t[4 * maxn];

void build(int l, int r, int k)
{
	int mid;
	t[k].l = l;
	t[k].r = r;
	t[k].ls = t[k].rs = t[k].ms = r - l + 1;
	if (l == r)
	  return;
    mid = (l + r) / 2;
    build(l, mid, 2 * k);
    build(mid + 1, r, 2 * k + 1);

}

void add(int i, int r, int x)
{
	int mid;
	if (t[i].r == t[i].l)
	{
		t[i].ls = t[i].rs = t[i].ms = x;
		return;
	}
	mid = (t[i].r + t[i].l) / 2;
	if (r <= mid)
		add(2 * i, r, x);
	else
		add(2 * i + 1, r, x);
	if (t[i * 2].ls == t[i * 2].r - t[i * 2].l + 1)
		t[i].ls = t[i * 2].ls + t[i * 2 + 1].ls;
	else
		t[i].ls = t[i * 2].ls;
	if (t[i * 2 + 1].rs == t[i * 2 + 1].r - t[i * 2 + 1].l + 1)
		t[i].rs = t[i * 2 + 1].rs + t[i * 2].rs;
	else
		t[i].rs = t[i * 2 + 1].rs;
	t[i].ms = max(max(t[i * 2].ms, t[i * 2 + 1].ms), t[i * 2].rs + t[i * 2 + 1].ls);

}

int findd(int k, int r)
{
	int mid;
	if (t[k].l == t[k].r || t[k].ms == 0 || t[k].ms == t[k].r - t[k].l + 1)
	{
		return t[k].ms;
	}
	mid = (t[k].r + t[k].l) / 2;
	if (r <= mid)
	{
		if (r >= t[2 * k].r - t[2 * k].rs + 1)
			return t[k * 2].rs + t[k * 2 + 1].ls;
		else
			return findd(2 * k, r);
	}
	else
	{
		if (r <= t[2 * k + 1].l + t[2 * k + 1].ls - 1)
			return t[k * 2 + 1].ls + t[k * 2].rs;
		else
			return findd(2 * k + 1, r);
	}
}
int main()
{
	int n, m, a;
	char str[10];
	while(~scanf("%d%d", &n, &m))
	{
    build(1, n, 1);
	stack<int>q;
	if(!q.empty())
        q.pop();
	while (m--)
	{
		scanf("%s", str);
		if (str[0] == 'D')
		{
			scanf("%d", &a);
			q.push(a);
			add(1, a, 0);
		}
		else if (str[0] == 'Q')
		{
			scanf("%d", &a);
			printf("%d\n", findd(1, a));
		}
		else if (str[0] == 'R')
		{
			a = q.top();
			q.pop();
			add(1, a, 1);
		}
	}
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/alpacadh/p/8521606.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值