hdu 1540 & poj 2892 Tunnel Warfare 线段树区间合并

31 篇文章 0 订阅
17 篇文章 0 订阅

基础线段树区间合并,详见代码

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;

const int N = 500010;

stack < int > s;

int n, m;
struct node{
	int l, r;
	int ls, rs;
}tr[N << 2];

void build( int l, int r, int rt )
{
	tr[rt].l = l;
	tr[rt].r = r;
	tr[rt].ls = tr[rt].rs = ( r - l + 1 );
	if( l == r )
		return;
	int mid = (l + r) >> 1;
	build( lson );
	build( rson );
}

void pushup( int rt )
{
	tr[rt].ls = tr[rt << 1].ls;
	tr[rt].rs = tr[rt << 1 | 1].rs;
	//如果左子树全为1,那么左子树长度要加上右子树的左边(下面也为同理) 
	if( tr[rt << 1].ls == tr[rt << 1].r - tr[rt << 1].l + 1 )
		tr[rt].ls += tr[rt << 1 | 1].ls;
	if( tr[rt << 1 | 1].rs == tr[rt << 1 | 1].r - tr[rt << 1 | 1].l + 1 )
		tr[rt].rs += tr[rt << 1].rs;
}

void update( int pos, int sta, int rt )
{
	//单点更新 
	if( tr[rt].l == tr[rt].r )
	{
		tr[rt].ls = tr[rt].rs = sta;
		return;
	}
	int mid = ( tr[rt].l + tr[rt].r ) >> 1;
	if( pos <= mid )
		update( pos, sta, rt << 1 );
	else
		update( pos, sta, rt << 1 | 1 );
	//回溯 
	pushup( rt );
}

int query( int pos, int rt )
{
	//单点查询 
	if( tr[rt].l == tr[rt].r )
		return tr[rt].ls;
	int mid = ( tr[rt].l + tr[rt].r ) >> 1;
	if( pos <= mid )
	{
		//查询位置在左子树的右边,则要加上右子树的左边,(下面同理) 
		if( pos >= mid - tr[rt << 1].rs + 1 )
			return tr[rt << 1].rs + tr[rt << 1 | 1].ls;
		return query( pos, rt << 1 );
	}	
	else
	{
		if( pos <= mid + tr[rt << 1 | 1].ls )
			return tr[rt << 1].rs + tr[rt << 1 | 1].ls;
		return query( pos, rt << 1 | 1 );
	}
}

int main()
{
	while(~scanf("%d%d", &n, &m))
	{
		build( 1, n, 1 );
		while( !s.empty() )
			s.pop();
		while( m-- )
		{
			int a;
			char op[10];
			scanf("%s", op);
			if( op[0] == 'R' )
			{
				if( s.empty() )
					continue;
				else
				{
					update( s.top(), 1, 1 );
					s.pop();
				}
			}
			else
			{
				scanf("%d", &a);
				if( op[0] == 'D' )
				{
					update( a, 0, 1 );
					s.push(a);
				}
				else
				{
					int ans = query( a, 1 );
					printf("%d\n", ans);
				}
			}
		}
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值