zoukankan      html  css  js  c++  java
  • 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
    ");
    			    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
    ",sum);
    			    }
    			}
    			else if(op == 'R'){
    				if(top > 0)
    					rebuild(1,stack[--top]);
    			}
    		}
    	}
    
    	return 0;
     }
    
  • 相关阅读:
    Android属性动画
    android 保存配置文档
    android 不自动弹出虚拟键盘
    android 常用代码
    android imageswitcher gallery 根据数据库内图片名字进行查看/删除
    android 文件内容和 textview 操作
    用 java 语言获取 1N 的不重复随机数
    android 数据库 备份还原
    解决Ubuntu 输入法不显示
    android 添加文本内容到sqlite表中
  • 原文地址:https://www.cnblogs.com/jxgapyw/p/4762672.html
Copyright © 2011-2022 走看看