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.\n");
                    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\n" , fr - 1 , ed - 1);
            }
            if(k == 2) {
                a++ , f++;
                int res = query(a , f , 1);
                updata(a , f , 1 , -1);
                printf("%d\n" , res);
            }
        }
        printf("\n");
    }
    return 0;
}
posted @ 2016-12-09 12:01  Gealo  阅读(173)  评论(0编辑  收藏  举报