poj 2892 || hdu 1540 Tunnel Warfare

80 篇文章 0 订阅

又是找区间最长的什么什么的。和hotel前期处理差不多。都需要记录从左边开始的连续的最大值,从右边开始的连续最大值,以及整个区间的最大值。

不同的是,这个题的R D操作都是基于点的操作,所以不需要用 lazy思想了,直接更新到底。

至于查询,纠结了,参考了别人的代码,我发现我脑子还是有点转不过来哎。。。其实那种做法也想到了,就是感觉有点麻烦 = =。。。

注意查询临界情况,已经摧毁的用栈存了即可。


#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")

using namespace std;

const int MAX = 50010;
struct Tnode{ int cover,l,r,lval,rval,sum;};
Tnode node[MAX<<2];
stack<int> s;

void init()
{
	memset(node,0,sizeof(node));
}
void Build(int t,int l,int r)
{
	node[t].l = l; node[t].r = r;
	node[t].lval = node[t].rval = node[t].sum = r - l;
	node[t].cover = 1;
	if( l == r - 1 ) return ;
	int mid = MID(l,r);
	Build(L(t),l,mid);
	Build(R(t),mid,r);
}

void Updata_sum(int t)
{
	if( node[R(t)].cover == 0 && node[L(t)].cover == 0 )
		node[t].cover = 0;
	else
		if( node[R(t)].cover == 1 && node[L(t)].cover == 1 )
			node[t].cover = 1;
		else
			node[t].cover = -1;
	node[t].lval = node[L(t)].lval + ( node[L(t)].cover == 1 ? node[R(t)].lval : 0 );
	node[t].rval = node[R(t)].rval + ( node[R(t)].cover == 1 ? node[L(t)].rval : 0 );
	node[t].sum = max(node[t].rval,max(node[t].lval,node[L(t)].rval + node[R(t)].lval));
}

void Updata(int t,int l,int r,int val)
{
	if( node[t].l >= l && node[t].r <= r )
	{
		node[t].cover = node[t].lval = node[t].rval = node[t].sum = val;
		return ;
	}
	if( node[t].l == node[t].r - 1 ) return ;
	int mid = MID(node[t].l,node[t].r);
	if( l <= mid )
		Updata(L(t),l,r,val);
	if( r > mid )
		Updata(R(t),l,r,val);
	Updata_sum(t);
}

int Query(int t,int l)
{
	if( node[t].cover == 1 ) return node[t].sum;
	if( node[t].cover == 0 ) return 0;
	int mid = MID(node[t].l,node[t].r);
	if( l < mid )
	{
		if( mid - l <= node[L(t)].rval )
			return node[L(t)].rval + node[R(t)].lval;
		return Query(L(t),l);
	}
	else
	{
		if( l - mid + 1 <= node[R(t)].lval )
			return node[L(t)].rval + node[R(t)].lval;
		return Query(R(t),l);
	}
	
}
int main()
{
	int n,m,x;
	char ch[2];
	while( ~scanf("%d%d",&n,&m) )
	{
		init();
		Build(1,0,n);
		while( !s.empty() ) s.pop();
		while( m-- )
		{
			scanf("%s",ch);
			if( ch[0] == 'D' )
			{
				scanf("%d",&x);
				Updata(1,x-1,x,0);
				s.push(x);
			}
			if( ch[0] == 'R' )
			{
				if( s.empty() ) break;
				x = s.top(); s.pop();
				Updata(1,x-1,x,1);
			}
			if( ch[0] == 'Q' )
			{
				scanf("%d",&x);
				int ans = Query(1,x-1);
				printf("%d\n",ans);
			}
		}
	}
return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值