HDU1540(线段树+最大连续区间和)

题目大意:1-n个地道,m个次操作,D代表摧毁第i个地道,Q代表查询包含第i个地道的最大连续地道数目,并输出。R代表修复最近摧毁的那个地道

解题思路:由于题目中说明R表示修复最近摧毁的那个通道,所以自然而然的想到利用栈来解决,在本题中使用数组来模拟栈操作,其次,Q代表查询包含第i个地道的最大连续地道数目,这个就表示要求求出包含在本节点在内的最大连续区间的和。在下面解题中,1表示地道未被炸毁,0表示地道被炸毁。

求最大连续区间的和的方法:维护区间中从左节点开始的最大连续区间和区间中从右节点开始的最大连续区间和,以及在这个区间中最大连续区间和

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAXN = 50005;
int n,m;
int sta[MAXN],top;

struct Tree
{
	int l,r;
	int msm,lsm,rsm;
}tree[4*MAXN];

void Build(int i,int l,int r)
{
	tree[i].l = l;
	tree[i].r = r;
	if(l == r)
	{
		tree[i].msm = tree[i].lsm = tree[i].rsm = 1;
		return;
	}
	int mid = (l+r)>>1;
	Build(i<<1,l,mid);
	Build(i<<1|1,mid+1,r);
	tree[i].msm = tree[i<<1].msm + tree[i<<1|1].msm;
	tree[i].lsm = tree[i].rsm = tree[i].msm;
}

void Update(int i,int mem,int res)
{
	if(tree[i].l == tree[i].r)
	{
		tree[i].msm = tree[i].lsm = tree[i].rsm = res;
		return;
	}
	int mid = (tree[i].l+tree[i].r)>>1;
	if(mem <= mid) Update(i<<1,mem,res);
	else Update(i<<1|1,mem,res);

	tree[i].msm = max(max(tree[i<<1].msm,tree[i<<1|1].msm),tree[i<<1].rsm+tree[i<<1|1].lsm);
	if(tree[i<<1].lsm == tree[i<<1].r-tree[i<<1].l+1)
		tree[i].lsm = tree[i<<1].lsm + tree[i<<1|1].lsm;
	else
		tree[i].lsm = tree[i<<1].lsm;
	if(tree[i<<1|1].rsm==tree[i<<1|1].r-tree[i<<1|1].l+1)
		tree[i].rsm = tree[i<<1|1].rsm + tree[i<<1].rsm;
	else
		tree[i].rsm = tree[i<<1|1].rsm;

}

int Query(int i,int mem)
{
	if(tree[i].l==tree[i].r || tree[i].msm==0 || tree[i].msm == tree[i].r-tree[i].l+1)
		return tree[i].msm;
	int mid = (tree[i].l+tree[i].r)>>1;
	if(mem <= mid)
	{
		if(mem >= (tree[i<<1].r-tree[i<<1].rsm+1))
			return tree[i<<1].rsm + Query(i<<1|1,mid+1);
		else
			return Query(i<<1,mem);
	}else
	{
		if(mem <= (tree[i<<1|1].l+tree[i<<1|1].lsm-1))
			return tree[i<<1|1].lsm + Query(i<<1,mid);
		else
			return Query(i<<1|1,mem);
	}
}

int main()
{
	char ch[2];
	int mem,ans;
	while(~scanf("%d%d",&n,&m))
	{
		top = 0;
		Build(1,1,n);
		while(m--)
		{
			scanf("%s",ch);
		    if(ch[0]=='D')
			{
				scanf("%d",&mem);
			    sta[++top] = mem;
			    Update(1,mem,0);
		    }else
			    if(ch[0]=='Q')
			    {
					scanf("%d",&mem);
				    ans = Query(1,mem);
				    printf("%d\n",ans);
			    }else
			    {
				    Update(1,sta[top],1);
				    top--;
			    }
		}
	}
	return 0;
}
发布了33 篇原创文章 · 获赞 2 · 访问量 1725

猜你喜欢

转载自blog.csdn.net/weixin_42469716/article/details/102938021