hdu1540 Tunnel Warfare 线段树区间合并

题意:n个城镇在一条直线上,初始状态相邻的城镇都相邻。有三种操作:(1) D x 摧毁x城镇 (2) R 修复上次摧毁的城镇 (3) Q x 查询

与x相连的没有被摧毁的城镇。

思路:线段树维护2个变量:ls存区间左端向右连续完好城镇的个数,rs存区间右端向左连续玩好城镇的个数。对于D相当于单点更

新。对于R需要用个栈存之前摧毁的城镇。对于Q稍微麻烦点。要判断p是否在区间的ls、rs里。如果在,那么需要将另一端的与它相

连的部分加上再return。详见代码:

// file name: hdu1540.cpp //
// author: kereo //
// create time:  2014年09月08日 星期一 16时05分47秒 //
//***********************************//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int MAXN=50000+100;
const int inf=0x3fffffff;
const int mod=1000000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
int n,m,top;
int s[MAXN];
struct node
{
	int l,r;
	int ls,rs; //ls记录从区间左端向右连续没有被破坏的village个数,rs记录从右段向左。
}segtree[MAXN<<2];
void push_up(int rt){
	segtree[rt].ls=segtree[L(rt)].ls;
	segtree[rt].rs=segtree[R(rt)].rs;
	if(segtree[L(rt)].ls == segtree[L(rt)].r-segtree[L(rt)].l+1)
		segtree[rt].ls+=segtree[R(rt)].ls;
	if(segtree[R(rt)].rs == segtree[R(rt)].r-segtree[R(rt)].l+1)
		segtree[rt].rs+=segtree[L(rt)].rs;
}
void build(int rt,int l,int r){
	segtree[rt].l=l; segtree[rt].r=r;
	segtree[rt].ls=segtree[rt].rs=r-l+1;
	if(l == r)
		return ;
	int mid=(l+r)>>1;
	build(L(rt),l,mid); build(R(rt),mid+1,r);
}
void update(int rt,int p,int cmd){ //cmd=0,删除;cmd=1,恢复
	if(segtree[rt].l == segtree[rt].r){
		segtree[rt].ls=segtree[rt].rs=cmd;
		return ;
	}
	int mid=(segtree[rt].l+segtree[rt].r)>>1;
	if(p<=mid)
		update(L(rt),p,cmd);
	else 
		update(R(rt),p,cmd);
	push_up(rt);
}
int query(int rt,int p){
	//printf("%d %d\n",segtree[rt].l,segtree[rt].r);
	if(segtree[rt].ls>=p-segtree[rt].l+1)
		return segtree[rt].ls;
	if(segtree[rt].rs>=segtree[rt].r-p+1)
		return segtree[rt].rs;	
	if(segtree[rt].l == segtree[rt].r)
		return 0;
	int mid=(segtree[rt].l+segtree[rt].r)>>1;
	if(p<=mid){
		int ans=query(L(rt),p);
		if(segtree[L(rt)].rs>=segtree[L(rt)].r-p+1)
			ans+=segtree[R(rt)].ls;
		return ans;
	}
	else{
		int ans=query(R(rt),p);
		if(segtree[R(rt)].ls>=p-segtree[R(rt)].l+1)
			ans+=segtree[L(rt)].rs;
		return ans;
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m)){
		build(1,1,n);
		top=0;
		int x;
		char cmd[2];
		while(m--){
			scanf("%s",cmd);
			if(cmd[0] == 'D'){
				scanf("%d",&x);
				s[top++]=x;
				update(1,x,0);	
			}
			if(cmd[0] == 'R'){
				x=s[--top];
				update(1,x,1);
			}
			if(cmd[0] == 'Q'){
				scanf("%d",&x);;
				printf("%d\n",query(1,x));
			}
		}
	}
	return 0;
}


你可能感兴趣的:(线段树)