zoukankan      html  css  js  c++  java
  • [Tunnel Warfare] [HDU

    [Tunnel Warfare] [HDU - 1540]( Problem - 1540 (hdu.edu.cn) ) T4 D3

    1.线段树单点修改 、区间合并

    思路:

    1表示当前村子没被摧毁,0表示摧毁了

    llen 表示当前区间左端点向右连续的1的个数

    rlen 表示当前区间右端点向左连续的1的个数

    用线段树维护 llen, rlen

    询问时:

    • k在左子树
      • 若k在左子树的rlen中,返回左子树的rlen+右子树的llen
      • 否则递归左子树
    • k在右子树
      • 若k在右子树的llen中,返回左子树的rlen+右子树的llen
      • 否则递归右子树

    参考代码

    #include<bits/stdc++.h>
    #define ll long long 
    #define ls (p<<1)
    #define rs ((p<<1)|1)
    #define mid ((t[p].l+t[p].r)>>1) 
    using namespace std;
    int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
    inline void Prin(int x){if(x < 0){putchar('-');x = -x;}if(x > 9) Prin(x / 10);putchar(x % 10 + '0');}
    const int qs=1e5+7;
    struct Tree{
    	int l,r,llen,rlen;
    	#define l(x) t[x].l
    	#define r(x) t[x].r
    	#define llen(x) t[x].llen
    	#define rlen(x) t[x].rlen
    }t[qs<<2];
    int a[qs],cnt,n,q;
    
    void pushup(int p){
    	llen(p)=llen(ls)+(llen(ls)==r(ls)-l(ls)+1 ? llen(rs) : 0);
    	rlen(p)=rlen(rs)+(rlen(rs)==r(rs)-l(rs)+1 ? rlen(ls) : 0);
    }
    
    void build(int p,int l,int r){
    	l(p)=l,r(p)=r;
    	if(l==r) {
    		llen(p)=rlen(p)=1;
    		return;
    	}
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    	pushup(p);
    }
    
    void update(int p,int l,int r,int k){
    	if(l<=l(p)&&r>=r(p)){
    		llen(p)=rlen(p)=k;
    		return;
    	}
    	if(l<=mid) update(ls,l,r,k);
    	if(r>mid) update(rs,l,r,k);
    	pushup(p);
    }
    
    int ask(int p,int l,int r){
    	if(l<=l(p)&&r>=r(p)) return llen(p);
    	if(l<=mid){
    		if(l>=r(ls)-rlen(ls)+1) return rlen(ls)+llen(rs);
    		else return ask(ls,l,r);
    	}
    	if(r>mid) { 
    		if(r<=l(rs)+llen(rs)-1) return rlen(ls)+llen(rs);
    		else return ask(rs,l,r);
    	}
    	return 0;
    } 
    
    int main(){
    	while(~scanf("%d%d",&n,&q)){	
    	build(1,1,n);
    	cnt=0;
    	//getchar();
    	while(q--){
    		char c;int k;
    		cin>>c;
    		if(c=='R'){
    			k=a[cnt];
    			update(1,k,k,1);
    			cnt--;
    			continue;
    		} 
    		k=read();
    		if(c=='D'){
    			a[++cnt]=k;
    			update(1,k,k,0);
    		}
    		else{
    			int ans=ask(1,k,k);
    			Prin(ans);
    			puts("");
    		}
    	}	
    }
    	return 0;
    }
    

    2.set+二分

    思路:

    set时自动排序的(int默认升序),查找一个村庄的情况时,只需要找到这个村庄标号两边被毁的最近的村子。相减即可,查找过程二分。

    参考代码

    #include<bits/stdc++.h>
    #define ll long long 
    #define ls (p<<1)
    #define rs ((p<<1)|1)
    #define mid ((t[p].l+t[p].r)>>1) 
    using namespace std;
    int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
    inline void Prin(int x){if(x < 0){putchar('-');x = -x;}if(x > 9) Prin(x / 10);putchar(x % 10 + '0');}
    const int qs=1e5+7;
    int n,cnt,q,a[qs];
    int main(){
    	while(~scanf("%d%d",&n,&q)){
    	cnt=0;
    	set<int> s;
    	s.insert(0),s.insert(n+1);
    	while(q--){
    		char c;int k;
    		cin>>c;
    		
    		if(c=='R'){
    			k=a[cnt];
    			s.erase(k);
    			cnt--;
    			continue;
    		} 
    		k=read();
    		if(c=='D'){
    			a[++cnt]=k;
    			s.insert(k);
    		}
    		else{
    			if(s.find(k)!=s.end()){
    				cout<<"0
    ";
    				continue;
    			}
    			int l=*(--s.upper_bound(k));
    			int r=*(s.upper_bound(k));
    			Prin(r-l-1);
    			puts("");
    		}
    	}	
    	}
    	return 0;
    }
    
  • 相关阅读:
    Review Python装饰器
    Python自动化开发三元运算 列表解析 生成器表达式
    Python自动化开发函数02
    Python自动化开发函数03
    Python自动化开发文件
    ELK02ELK收集Linux系统平台应用系统日志
    ELK01Elasticsearch
    html5调用摄像头并拍照
    Docker 安装 PostgreSQL
    《TensorFlow+Keras自然语言处理实战》图书介绍
  • 原文地址:https://www.cnblogs.com/Suki-Sugar/p/15139691.html
Copyright © 2011-2022 走看看