zoukankan      html  css  js  c++  java
  • Tunnel Warfare 线段树 区间合并|最大最小值

    B - Tunnel WarfareHDU - 1540

    这个有两种方法,一个是区间和并,这个我个人感觉异常恶心

    第二种方法就是找最大最小值  kuangbin——线段树专题 H - Tunnel Warfare <-- 这个博客讲的很清楚

    #include <cstdio>//法一:最大值最小值法,这个就是每一个点,如果这个点没有被摧毁,那就找到这个点最左边的和最右边的
    #include <cstdlib>//最大-最小+1.这个就是这个最大连续长度。
    #include <queue>//建树,很简单,主要就是query和update。
    #include <algorithm>//这个地方的怎么去找一个包含一个数的一个区间的最大最小值呢?
    #include <vector>//这个就是从上面往下面查询的过程中,就去找,如果是找最大值就去max,最小值就取min
    #include <cstring>//这个要注意建树,这个区间的最大值的意思是,小于等于这个数的最大的被炸了的村庄,这个就说明,开始最大值为0,因为没有任何一个村庄被炸
    #include <string>//区间的最小值,意思是大于等于这个数,被炸了的村庄的最小值,开始为n+1.因为没有村庄被炸。
    #include <iostream>
    #include <stack>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 100;
    struct node
    {
        int l, r;
        int mx, mn;
    }tree[maxn*4];
    int n;
    void build(int id,int l,int r)
    {
        tree[id].l = l;
        tree[id].r = r;
        if(l==r)
        {
            tree[id].mn = n+1;
            tree[id].mx = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        tree[id].mx = max(tree[id << 1].mx, tree[id << 1 | 1].mx);
        tree[id].mn = min(tree[id << 1].mn, tree[id << 1 | 1].mn);
    }
    
    void update_max(int id,int x,int z)
    {
        if(tree[id].l==tree[id].r)
        {
            tree[id].mx = z;
            return;
        }
        int mid = (tree[id].l + tree[id].r) >> 1;
        if(x<=mid) update_max(id << 1, x, z);
        if (x > mid) update_max(id << 1 | 1, x, z);
        tree[id].mx = max(tree[id << 1].mx, tree[id << 1 | 1].mx);
    }
    
    void update_min(int id,int x,int z)
    {
        if(tree[id].l==tree[id].r)
        {
            tree[id].mn = z;
            return;
        }
        int mid = (tree[id].l + tree[id].r) >> 1;
        if (x <= mid) update_min(id << 1, x, z);
        if (x > mid) update_min(id << 1 | 1, x, z);
        tree[id].mn = min(tree[id << 1].mn, tree[id << 1 | 1].mn);
    }
    
    int query_max(int id,int x,int y)
    {
        int ans = 0;
        if(x<=tree[id].l&&y>=tree[id].r)
        {
            return tree[id].mx;
        }
        int mid = (tree[id].l + tree[id].r) >> 1;
        if (x <= mid) ans = max(ans, query_max(id << 1, x, y));
        if (y > mid) ans = max(ans, query_max(id << 1 | 1, x, y));
        return ans;
    }
    
    int query_min(int id,int x,int y)
    {
        int ans = inf;
        if(x<=tree[id].l&&y>=tree[id].r)
        {
            return tree[id].mn;
        }
        int mid = (tree[id].l + tree[id].r) >> 1;
        if (x <= mid) ans = min(ans, query_min(id << 1, x, y));
        if (y > mid) ans = min(ans, query_min(id << 1 | 1, x, y));
        return ans;
    }
    
    int main()
    {
        
        int m, x;
        while(cin >> n >> m)
        {
            stack<int>sta;
            build(1, 1, n);
            while(m--)
            {
                char s[10];
                scanf("%s", s);
                if(s[0]=='D')
                {
                    cin >> x;
                    update_max(1, x, x);
                    update_min(1, x, x);
                    sta.push(x);
                }
                if(s[0]=='R')
                {
                    int y = sta.top(); sta.pop();
                    update_max(1, y, 0);
                    update_min(1, y, n + 1);
                }
                if(s[0]=='Q')
                {
                    cin >> x;
                    int L = query_min(1, x, n + 1);
                    int R = query_max(1, 0, x);
                    //printf("%d %d
    ", L, R);
                    if (L == R) printf("0
    ");
                    else printf("%d
    ", L - R - 1);
                }
            }
        }
        
        return 0;
    }
    方法一
    //法二:区间合并,这个应该更好懂一点,就是维护一下一个区间的前缀后缀长度
    //这个更新应该比较简单,
    #include <cstdio>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <stack>
    #define inf 0x3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 100;
    struct node
    {
        int l, r, len;
        int max_pre, max_last;
    }tree[maxn*4];
    
    void push_up(int id)
    {
        tree[id].max_pre = tree[id << 1].max_pre;
        tree[id].max_last = tree[id << 1 | 1].max_last;
        if (tree[id << 1].max_pre == tree[id << 1].len)
        {
            tree[id].max_pre += tree[id << 1 | 1].max_pre;
        }
        if(tree[id<<1|1].max_last==tree[id<<1|1].len)
        {
            tree[id].max_last += tree[id << 1].max_last;
        }
    }
    
    void build(int id,int l,int r)
    {
        tree[id].l = l;
        tree[id].r = r;
        tree[id].len = r - l + 1;
        if(l==r)
        {
            tree[id].max_pre = tree[id].max_last = 1;
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        push_up(id);
    }
    
    void update(int id,int x,int z)
    {
        if(tree[id].l==tree[id].r)
        {
            tree[id].max_pre = z;
            tree[id].max_last = z;
            return;
        }
        int mid = (tree[id].l + tree[id].r) >> 1;
        if (x <= mid) update(id << 1, x, z);
        else update(id << 1 | 1, x, z);
        push_up(id);
    }
    
    int query_pre(int id,int x,int y)
    {
        int ans = 0, res = 0;
        if(x<=tree[id].l&&y>=tree[id].r)
        {
            //printf("tree[%d].max_pre=%d
    ", id, tree[id].max_pre);
            return tree[id].max_pre;
        }
        //printf("id=%d x=%d y=%d
    ", id, x, y);
        int mid = (tree[id].l + tree[id].r) >> 1;
        if (x <= mid) ans=query_pre(id << 1, x, y);
        if (y > mid) res=query_pre(id << 1 | 1, x, y);
        //printf("id=%d ans=%d res=%d mid=%d
    ",id, ans, res,mid);
        if (ans >= mid - x + 1)
        {
            //printf("tree[%d].max_pre=%d mid=%d x=%d
    ",id, tree[id].max_pre, mid, x);
            ans += res;
        }
        return ans;
    }
    
    int query_last(int id,int x,int y)
    {
        int ans = 0, res = 0;
        if (x <= tree[id].l&&y >= tree[id].r)
        {
            //printf("tree[%d].last=%d
    ", id, tree[id].max_last);
            return tree[id].max_last;
        }
        //printf("id=%d x=%d y=%d
    ", id, x, y);
        int mid = (tree[id].l + tree[id].r) >> 1;
        if (x <= mid) ans = query_last(id << 1, x, y);
        if (y > mid) res = query_last(id << 1 | 1, x, y);
        //printf("id=%d mid=%d ans=%d res=%d
    ", id, mid,ans, res);
        if (res >= y-mid)
        {
            //printf("tree[%d].max_last=%d  mid=%d x=%d
    ",id,tree[id].max_last, mid, x);
            res += ans;
        }
        return res;
    }
    
    int main()
    {
        int n, m;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            stack<int>sta;
            build(1, 1, n);
            while(m--)
            {
                char s[10];
                scanf("%s", s);
                if(s[0]=='D')
                {
                    int x;
                    cin >> x;
                    update(1, x, 0);
                    sta.push(x);
                }
                if(s[0]=='R')
                {
                    int y = sta.top(); sta.pop();
                    update(1, y, 1);
                }
                if(s[0]=='Q')
                {
                    int x;
                    cin >> x;
                    int ans = query_pre(1, x, n);
                    ans += query_last(1, 1, x);
                    if(ans) printf("%d
    ", ans-1);
                    else printf("0
    ");
                }
            }
        }
        return 0;
    }
    /*
    7 10
    D 3
    D 6
    D 5
    Q 4
    Q 5
    R
    Q 4
    R
    Q 4
    Q 3
     */
    方法二
     
  • 相关阅读:
    如何改变Activity在当前任务堆栈中的顺序,Intent参数大全
    SQL删除重复记录,并只保留一条
    SpringCloud+Eureka+Feign+Ribbon+zuul的简化搭建流程和CRUD练习
    Spring Cloud Bus 消息总线
    Spring Cloud之Swagger集群搭建
    nginx-ZUUL集群
    spring boot swagger-ui.html 404
    jenkins 部署docker 容器 eureka 集群 完整配置 多台服务器
    Linux(Centos)之安装Nginx及注意事项
    Idea 导出Modules =>jar
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/10802782.html
Copyright © 2011-2022 走看看