HDU 1540 Tunnel Warfare (线段树)

题目大意: n 个村庄排列在一条直线上,相邻的村庄有地道连接,除首尾两个村庄外,其余村庄都有两个相邻的村庄。其中有 3 中操作 D x :表示摧毁编号为 x 的村庄,Q x:表示求出包含村庄 x 的最长区间中村庄的数目,R 表示修复最后摧毁的村庄。输入 n,m 分别表示村庄的树木,和操作的次数。
思路 : 当查询包含 村庄 x 的最长区间的村庄数时,可以求出位于 区间 [1,x-1] 中被摧毁的最大村庄编号,求出[x+1,n] 中被摧毁的最小村庄的编号。由此便可求出结果。
可利用线段树存储区间内的被摧毁的村庄的最大和最小编号。

代码:

 #include<iostream>
 #include<cstdio>
 #include<cstdlib>
 #include<cstring>
 #include<queue>
 #include<algorithm>
 #include<cmath>
 #include<map>
 using namespace std;
 #define INF 100000000

 int n,m;
 struct node{
	int l;
	int r;
	int MAX;
	int MIN;
 }a[201000];

 void buildtree(int i,int l,int r){
	a[i].l = l ;
	a[i].r = r ;
	a[i].MAX = -INF ;
	a[i].MIN = INF ;
	if(l == r)
	    return ;
	int mid = (l+r)/2;
	buildtree(i*2,l,mid);
	buildtree(i*2+1,mid+1,r);
 }

 void Destory(int i,int x){
	a[i].MAX = max(a[i].MAX,x);
	a[i].MIN = min(a[i].MIN,x);
	if(a[i].l == a[i].r)
	    return ;
	int mid = (a[i].l + a[i].r) / 2;
	if(x <= mid)
	    Destory(i*2,x);
	else
	    Destory(i*2+1,x);
 }

 int Querymax(int i,int l,int r){
 	if(a[i].l == l && a[i].r == r){
		return a[i].MAX ;
	}
	if(a[i].l == a[i].r)
	    return a[i].MAX;
	int ans = -INF;
	int mid = (a[i].l + a[i].r) / 2 ;
	if(r <= mid)
	    ans = Querymax(i*2,l,r);
	else if(l > mid)
	    ans = Querymax(i*2+1,l,r);
	else{
		ans = max(ans,Querymax(i*2,l,mid));
		ans = max(ans,Querymax(i*2+1,mid+1,r));
	}
	return ans ;
 }

 int Querymin(int i,int l,int r){
	if(a[i].l == l && a[i].r == r)
		return a[i].MIN ;
	if(a[i].l == a[i].r)
	    return a[i].MIN;
	int ans = INF ;
	int mid = (a[i].l + a[i].r) / 2 ;
	if(r <= mid)
	    ans = Querymin(i*2,l,r) ;
	else if(l > mid)
	    ans = Querymin(i*2+1,l,r) ;
	else{
		ans = min(ans,Querymin(i*2,l,mid));
		ans = min(ans,Querymin(i*2+1,mid+1,r));
	}
	return ans ;
 }

 void rebuild(int i,int x){
	if(a[i].l == a[i].r){
		a[i].MAX = -INF ;
		a[i].MIN = INF ;
		return ;
 	}
 	int mid = (a[i].l + a[i].r) / 2 ;
 	if(x <= mid)
 	    rebuild(i*2,x);
	else
	    rebuild(i*2+1,x);
	a[i].MAX = max(a[i*2].MAX,a[i*2+1].MAX);
	a[i].MIN = min(a[i*2].MIN,a[i*2+1].MIN);
 }

 int main(){
	char op;
	int x,sum,top,stack[50000];
	while(~scanf("%d%d",&n,&m)){
		buildtree(1,1,n);
		top = 0;
		for(int k=1;k<=m;k++){
			getchar();
			scanf("%c",&op) ;
			if(op == 'D'){
				scanf("%d",&x);
				stack[top++] = x ;
				Destory(1,x);
			}
			else if(op == 'Q'){
				scanf("%d",&x);
			    int ans1 = Querymax(1,1,x);
			    int ans2 = Querymin(1,x,n);
			    if(ans1==x || ans2==x)
			        printf("0\n");
			    else {
			    	if(ans1 == -INF)
			    		sum = x - 1 ;
			    	else
			    	    sum = x - ans1 - 1 ;
			    	if(ans2 == INF) 
					    sum += n - x ;
					else  
			    		sum += ans2 - 1 - x;
			    	sum ++ ;
			    	printf("%d\n",sum);
			    }
			}
			else if(op == 'R'){
				if(top > 0)
					rebuild(1,stack[--top]);
			}
		}
	}

	return 0;
 }
posted @ 2015-08-27 10:58  阿文的博客  阅读(157)  评论(0编辑  收藏  举报