zoukankan      html  css  js  c++  java
  • hdu1540之线段树单点更新+区间合并


    Tunnel Warfare

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3318    Accepted Submission(s): 1280

    Problem Description
    During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.

    Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
     
    Input
    The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.

    There are three different events described in different format shown below:

    D x: The x-th village was destroyed.

    Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.

    R: The village destroyed last was rebuilt.
     
    Output
    Output the answer to each of the Army commanders’ request in order on a separate line.
     
    Sample Input
    7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
     
    Sample Output
    1 0 2 4

    分析:设置lsum[n],rsum[n]分别表示区间左端连续村庄个数,区间右端连续村庄个数

    查询的时候只要查询1~a右端连续个数+a~n左端连续个数,如果大于0就输出个数-1(因为a算了两次)

    写完百度了下别人的代码,发现别人写的线段树和自己写的不怎么一样,于是就想学学,奈何。。。实在是不愿意看别人的代码,特别是那些没格式的还比较乱的。。。自己太懒了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<map>
    #include<iomanip>
    #define INF 99999999
    using namespace std;
    
    const int MAX=50000+10;
    int lsum[MAX<<2],rsum[MAX<<2];//分别记录区间内最大连续村庄,左端最大连续村庄,右端最大连续村庄
    int s[MAX],size,n,m,a;//s记录破坏的村庄编号 
    char ch[2];
    bool mark[MAX];//mark标记村庄是否破坏,0表示没破坏,1表示破坏 
    
    void Upfather(int n,int m){//更新区间左右端连续村庄个数 
    	lsum[n]=lsum[n<<1];
    	rsum[n]=rsum[n<<1|1];
    	if(lsum[n] == m-(m>>1))lsum[n]+=lsum[n<<1|1];
    	if(rsum[n] == m>>1)rsum[n]+=rsum[n<<1];
    }
    
    void BuildTree(int left,int right,int n){
    	lsum[n]=rsum[n]=right-left+1;
    	if(left == right)return;
    	int mid=left+right>>1;
    	BuildTree(left,mid,n<<1);
    	BuildTree(mid+1,right,n<<1|1);
    }
    
    void Update(int p,int date,int left,int right,int n){
    	if(left == right){lsum[n]=(rsum[n]+=date);return;}
    	int mid=left+right>>1;
    	if(p<=mid)Update(p,date,left,mid,n<<1);
    	else Update(p,date,mid+1,right,n<<1|1);
    	Upfather(n,right-left+1);
    }
    
    int QueryL(int L,int R,int left,int right,int n){//查询a~n的左端连续村庄个数 
    	if(L<=left && right<=R)return lsum[n];
    	int mid=left+right>>1,lans,rans;
    	if(L<=mid)lans=QueryL(L,R,left,mid,n<<1);
    	if(R>mid)rans=QueryL(L,R,mid+1,right,n<<1|1);
    	if(R<=mid)return lans;
    	if(L>mid)return rans;
    	if(lans == mid-L+1)return lans+rans;
    	return lans;
    }
    /*另一种写法或许更好理解
    int QueryL(int L,int R,int left,int right,int n){
    	if(L<=left && right<=R)return lsum[n];
    	int mid=left+right>>1,lans,rans;
    	if(R<=mid)return QueryL(L,R,left,mid,n<<1);
    	else if(L>mid)return QueryL(L,R,mid+1,right,n<<1|1);
    	else{
    		lans=QueryL(L,mid,left,mid,n<<1);
    		rans=QueryL(mid+1,R,mid+1,right,n<<1|1);
    		if(lans == mid-L+1)return lans+rans;
    		return lans;
    	}
    } 
    */
    
    int QueryR(int L,int R,int left,int right,int n){//查询1~a右端村庄连续个数 
    	if(L<=left && right<=R)return rsum[n];
    	int mid=left+right>>1,lans,rans;
    	if(L<=mid)lans=QueryR(L,R,left,mid,n<<1);
    	if(R>mid)rans=QueryR(L,R,mid+1,right,n<<1|1);
    	if(R<=mid)return lans;
    	if(L>mid)return rans;
    	if(rans == R-mid)return lans+rans;
    	return rans;
    }
    /*另一种写法或许更好理解
    int QueryR(int L,int R,int left,int right,int n){
    	if(L<=left && right<=R)return rsum[n];
    	int mid=left+right>>1,lans,rans;
    	if(R<=mid)return QueryR(L,R,left,mid,n<<1);
    	else if(L>mid)return QueryR(L,R,mid+1,right,n<<1|1);
    	else{
    		lans=QueryR(L,mid,left,mid,n<<1);
    		rans=QueryR(mid+1,R,mid+1,right,n<<1|1);
    		if(rans == R-mid)return lans+rans;
    		return rans;
    	}
    }
    */
    
    int main(){
    	while(~scanf("%d%d",&n,&m)){
    		BuildTree(1,n,1);
    		size=0;
    		memset(mark,false,sizeof(bool)*(n+2));
    		mark[0]=true;
    		for(int i=0;i<m;++i){
    			scanf("%s",ch);
    			if(ch[0] == 'D'){
    				scanf("%d",&a);
    				s[++size]=a;
    				if(!mark[a])Update(a,-1,1,n,1),mark[a]=true;
    			}else if(ch[0] == 'R'){
    				while(!mark[s[size]])--size;//已经被修复过了就修复下一个,比如3 2 2,第一次修复2,现在修复3而不是2 
    				if(size)Update(s[size],1,1,n,1),mark[s[size--]]=false;
    			}else{
    				scanf("%d",&a);
    				int temp=QueryL(a,n,1,n,1)+QueryR(1,a,1,n,1);
    				printf("%d
    ",temp>0?temp-1:0);
    			}
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    上传图片,语音,和富文本(webuploader,dropzone, froala)
    java代码备份mysql数据库
    maven 父子工程打包 并且上传linux服务器
    docker+fastdfs+nginx 实现分布式大文件存储系统以及视频缓存播放
    docker eureka 注册中心 服务提供者通信机制
    lvs dr 模型配置详解
    spring cloud 详解
    JS前端创建CSV或Excel文件并浏览器导出下载
    修改ElementUI源码实践
    Leaflet+heatmap实现离线地图加载和热力图应用
  • 原文地址:https://www.cnblogs.com/pangblog/p/3320128.html
Copyright © 2011-2022 走看看