zoukankan      html  css  js  c++  java
  • hdu 4614 Vases and Flowers(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614

    题意:

    给你N个花瓶,编号是0  到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花

    然后有2个操作。

    1)a b 往在a位置后面(包括a)插b朵花,输出插入的首位置和末位置。

    2)a b 输出区间[a , b ]范围内的花的数量,然后全部清空。

    操作看起来挺简单的但写起来还是有点复杂的

    首先建树的时候可以设置变量first与ends分别表示一个区间最先出现的0和最后出现的0,sum=0

    表示没放东西,sum=1表示放了。我们可以用二分来查找插完b朵花后的结尾区间。然后在寻找这个

    区间的first与ends值之后就简单了。

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    const int M = 5e4 + 10;
    struct TnT {
        int l , r , num , add , first , ends;
    }T[M << 2];
    int n , m;
    void build(int l , int r , int p) {
        int mid = (l + r) >> 1;
        T[p].l = l , T[p].r = r , T[p].add = T[p].num = 0 , T[p].first = l , T[p].ends = r;
        if(l == r) {
            return ;
        }
        build(l , mid , p << 1);
        build(mid + 1 , r , (p << 1) | 1);
    }
    void pushup(int p) {
        T[p].num = T[p << 1].num + T[(p << 1) | 1].num;
        if(T[p << 1].first == -1) {
            T[p].first = T[(p << 1) | 1].first;
        }
        else if(T[(p << 1) | 1].first == -1) {
            T[p].first = T[p << 1].first;
        }
        else {
            T[p].first = min(T[(p << 1) | 1].first , T[p << 1].first);
        }
        if(T[(p << 1) | 1].ends == -1) {
            T[p].ends = T[(p << 1) | 1].ends;
        }
        else if(T[(p << 1) | 1].ends == -1) {
            T[p].ends = T[p << 1].ends;
        }
        else {
            T[p].ends = max(T[(p << 1) | 1].ends , T[p << 1].ends);
        }
    }
    void pushdown(int p) {
        if(T[p].add == 1) {
            T[p << 1].num = T[p << 1].r - T[p << 1].l + 1;
            T[p << 1].first = -1;
            T[p << 1].ends = -1;
            T[(p << 1) | 1].num = T[(p << 1) | 1].r - T[(p << 1) | 1].l + 1;
            T[(p << 1) | 1].first = -1;
            T[(p << 1) | 1].ends = -1;
            T[p << 1].add = T[p].add;
            T[(p << 1) | 1].add = T[p].add;
        }
        if(T[p].add == -1) {
            T[p << 1].first = T[p << 1].l;
            T[p << 1].ends = T[p << 1].r;
            T[p << 1].num = 0;
            T[(p << 1) | 1].num = 0;
            T[p << 1].add = T[p].add;
            T[(p << 1) | 1].first = T[(p << 1) | 1].l;
            T[(p << 1) | 1].ends = T[(p << 1) | 1].r;
            T[(p << 1) | 1].add = T[p].add;
        }
        T[p].add = 0;
    }
    int query(int l , int r , int p) {
        int mid = (T[p].l + T[p].r) >> 1;
        if(T[p].l == l && T[p].r == r) {
            return T[p].num;
        }
        pushdown(p);
        if(mid >= r) {
            return query(l , r , p << 1);
        }
        else if(mid < l) {
            return query(l , r , (p << 1) | 1);
        }
        else {
            return query(l , mid , p << 1) + query(mid + 1 , r , (p << 1) | 1);
        }
    }
    int queryfr(int l , int r , int p) {
        int mid = (T[p].l + T[p].r) >> 1;
        if(T[p].l == l && T[p].r == r) {
            return T[p].first;
        }
        pushdown(p);
        if(mid >= r) {
            return queryfr(l , r , p << 1);
        }
        else if(mid < l) {
            return queryfr(l , r , (p << 1) | 1);
        }
        else {
            int ans = queryfr(l , mid , p << 1);
            if(ans == -1) {
                return queryfr(mid + 1 , r , (p << 1) | 1);
            }
            else {
                return ans;
            }
        }
    }
    int queryed(int l , int r , int p) {
        int mid = (T[p].l + T[p].l) >> 1;
        if(T[p].l == l && T[p].r == r) {
            return T[p].ends;
        }
        pushdown(p);
        if(mid >= r) {
            return queryed(l , r , p << 1);
        }
        else if(mid < l) {
            return queryed(l , r , (p << 1) | 1);
        }
        else {
            int ans = queryed(mid + 1 , r , (p << 1) | 1);
            if(ans == -1) {
                return queryed(l , mid , p << 1);
            }
            else {
                return ans;
            }
        }
    }
    void updata(int l , int r , int p , int ad) {
        int mid = (T[p].l + T[p].r) >> 1;
        if(T[p].l == l && T[p].r == r) {
            if(ad == 1) {
                T[p].add = 1;
                T[p].num = T[p].r - T[p].l + 1;
                T[p].first = -1;
                T[p].ends = -1;
                return ;
            }
            if(ad == -1) {
                T[p].add = -1;
                T[p].num = 0;
                T[p].first = T[p].l;
                T[p].ends = T[p].r;
                return ;
            }
        }
        pushdown(p);
        if(mid >= r) {
            updata(l , r , p << 1 , ad);
        }
        else if(mid < l) {
            updata(l , r , (p << 1) | 1 , ad);
        }
        else {
            updata(l , mid , p << 1 , ad);
            updata(mid + 1 , r , (p << 1) | 1 , ad);
        }
        pushup(p);
    }
    int bisearch(int sta , int sum) {
        int l = sta , r = n;
        int ans = n;
        while(l <= r) {
            int mid = (l + r) >> 1;
            int gg = query(sta , mid , 1);
            gg = mid - sta + 1 - gg;
            if(gg >= sum) {
                r = mid - 1;
                ans = mid;
            }
            else {
                l = mid + 1;
            }
        }
        return ans;
    }
    int main() {
        int t;
        scanf("%d" , &t);
        while(t--) {
            scanf("%d%d" , &n , &m);
            build(1 , n , 1);
            for(int i = 1 ; i <= m ; i++) {
                int k , a , f;
                scanf("%d%d%d" , &k , &a , &f);
                if(k == 1) {
                    a++;
                    int res = query(a , n , 1);
                    res = n - a + 1 - res;
                    if(res == 0) {
                        printf("Can not put any one.
    ");
                        continue;
                    }
                    int sum = min(res , f);
                    int ed = bisearch(a , sum);
                    int fr = queryfr(a , ed , 1);
                    updata(fr , ed , 1 , 1);
                    printf("%d %d
    " , fr - 1 , ed - 1);
                }
                if(k == 2) {
                    a++ , f++;
                    int res = query(a , f , 1);
                    updata(a , f , 1 , -1);
                    printf("%d
    " , res);
                }
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    可视化工具D3.js教程 入门 (第十三章)—— 树状图
    可视化工具D3.js教程 入门 (第十二章)—— 力导向图
    可视化工具D3.js教程 入门 (第十一章)—— 饼图
    可视化工具D3.js教程 入门 (第十章)—— 交互式操作
    vue滑动页面选中标题,选中标题滚动到指定区域
    Vue样式穿透
    操作系统:进程和线程+进程的通讯方式
    客户端与服务端长连接的几种方式
    前端性能优化的 24 条建议(2020)-收藏
    idea中修改git提交代码的用户名
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6148944.html
Copyright © 2011-2022 走看看