zoukankan      html  css  js  c++  java
  • hdu 1540 Tunnel Warfare (线段树维护一维联通区间)

    • 题意: 一维线段上n个点,有摧毁和修复两种操作,询问某点最大的可达区域
    • 思路: 线段树维护(lsum)代表区间左端点开始最长联通区域,(rsum)代表右端点开始最长联通区域.单点修改只有(push_up)操作,用左子树(lsum)更像(lsum),右子树(rsum)更新(rsum)
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #define ll long long
    #define FOR(i,l,r) for(int i = l ; i <= r ;++i )
    #define inf 1<<30
    #define EPS (1e-9)
    #define lson(p) (p<<1)
    #define rson(p) (p<<1|1)
    using namespace std;
    typedef pair<int,int> pii;
    const int N = 5e5+30;
    int n,m;
    struct node{
        int l,r;
        int lsum,rsum;
    }a[N<<2];
    
    void push_up(int rt){
        a[rt].lsum = a[lson(rt)].lsum;  // 左二子更新左端点
        a[rt].rsum = a[rson(rt)].rsum;  // 右儿子更新右端点
        if(a[lson(rt)].lsum + a[lson(rt)].l-1 == a[lson(rt)].r){
            // 左儿子完全覆盖 扩充左区间
            a[rt].lsum  += a[rson(rt)].lsum;
        }
        if(a[rson(rt)].r - a[rson(rt)].rsum +1 == a[rson(rt)].l){
            // 右儿子完全覆盖 扩充右区间
            a[rt].rsum += a[lson(rt)].rsum;
        }
    }
    
    void build(int rt,int l,int r){
        a[rt].lsum = a[rt].rsum = r-l+1;
        a[rt].l = l; a[rt].r = r;
        if(l==r)  return ;
        int mid = (l+r)>>1;
        build(lson(rt),l,mid);
        build(rson(rt),mid+1,r);
    }
    
    
    void update(int rt,int p,int v){
        // 单点更新
        if(a[rt].l==p && a[rt].r ==p){
            a[rt].lsum = v;
            a[rt].rsum = v;
            return ;
        }
        int mid = (a[rt].l + a[rt].r)>>1;
        if(p<=mid)  update(lson(rt),p,v);
        else if(p>mid)   update(rson(rt),p,v);
        push_up(rt);
    }
    
    int query(int rt,int p){
        // 单点
        if(a[rt].l == a[rt].r )
            return a[rt].lsum;
        int mid = (a[rt].l + a[rt].r) >> 1;
        if(p<=mid){
            // p 在 左儿子的连续区间中,  左儿子的右区间与右儿子的左区间一定相邻 直接返回和
            if(p >= a[lson(rt)].r - a[lson(rt)].rsum +1){
                return a[lson(rt)].rsum + a[rson(rt)].lsum;
            }else{ // 否则递归查询左儿子
                return query(lson(rt),p);
            }
        }else{
            if(p <= a[rson(rt)].lsum + a[rson(rt)].l-1){
                return a[lson(rt)].rsum + a[rson(rt)].lsum;
            }else{
                return query(rson(rt),p);
            }
        }
    
    }
    char op[20];
    void solve(){
        stack<int> st;
        build(1,1,n);
        int pos ;
        FOR(i,1,m){
            scanf("%s",op);
            if(op[0]=='D'){
                scanf("%d",&pos);
                st.push(pos);
                update(1,pos,0);
            }else if(op[0]=='Q'){
                scanf("%d",&pos);
                printf("%d
    ",query(1,pos));
            }else{
                pos = st.top(); st.pop();
                update(1,pos,1);
            }
        }
    }
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            solve();
        }
        return 0;
    }
    
    

    当前节点与左右子节点区间的关系要搞清楚,只有单点修改,所以只存在用儿子更新父亲的情况.

  • 相关阅读:
    mac lsof使用查看端口
    mac 安装gevent报错
    vim命令学习
    linux批量关闭进程
    坐标点转换
    screen命令记录
    hashlib模块
    PyYAML和configparser模块讲解
    xml处理模块
    json、pickleshelve模块(超级好用~!)讲解
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11360510.html
Copyright © 2011-2022 走看看