hdu4614Vases and Flowers 线段树

//给一个数组,两个操作
//1 A F 以A为起点的F个空闲空间插花,输出起点和终点
//2 L R 将[L , R]的所有的有花的花拔除,问清除了几朵花
//用线段树维护剩余空间的个数
//然后再在查询时找出空间
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 50010 ;
#define left v<<1
#define right v<<1|1
struct node
{
    int l  ,r ,value ;
    int lazy ;
}tree[maxn<<2] ;
void build(int l , int r , int v)
{
    tree[v].l = l ;
    tree[v].r = r ;
    tree[v].value = (r - l + 1) ;
    tree[v].lazy = -1 ;
    if(l == r) return  ;
    int mid = (l + r) >> 1 ;
    build(l , mid , left) ;
    build(mid + 1 , r , right) ;
}
void push_down(int v)
{
    if(tree[v].lazy != -1)
    {
        tree[left].lazy = tree[right].lazy = tree[v].lazy ;
        tree[left].value = (tree[left].r - tree[left].l + 1)*tree[v].lazy ;
        tree[right].value = (tree[right].r - tree[right].l + 1)*tree[v].lazy ;
        tree[v].lazy = -1 ;
    }
}
int getsum(int l , int r , int v)
{
    if(l <= tree[v].l && tree[v].r <= r)
    return tree[v].value ;
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    if(r <= mid)return getsum(l , r , left) ;
    else if(l > mid)return getsum(l , r , right) ;
    else return getsum(l , mid , left) + getsum(mid+1 , r , right) ;
}
int  update(int l , int r , int op , int v)
{
    if(l <= tree[v].l && tree[v].r <= r)
    {
        int ans = (tree[v].r - tree[v].l + 1 - tree[v].value) ;
        tree[v].value = (tree[v].r - tree[v].l + 1)*op ;
        tree[v].lazy = op ;
        return ans;
    }
    push_down(v) ;
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    int ans ;
    if(l > mid)ans =  update(l , r , op , right) ;
    else if(r <= mid)ans = update(l , r , op , left) ;
    else ans = (update(l , mid , op , left) + update(mid + 1 , r , op , right)) ;
    tree[v].value = (tree[left].value + tree[right].value) ;
    return ans ;
}
int query(int pos , int &sum , int v)
{
    if(tree[v].l == tree[v].r)
    {
        if(tree[v].value == 1)sum--;
        return tree[v].l ;
    }
    int mid = (tree[v].l + tree[v].r) >> 1 ;
    push_down(v) ;
    if(pos <= mid)
    {
        int sum_1 = 0 ;
        if(pos > tree[v].l)
        sum_1 = getsum(tree[v].l , pos - 1 , left) ;
        int sum_2 = tree[left].value ;
        if(sum <= (sum_2 - sum_1))
        return query(pos , sum , left) ;
        sum -= (sum_2 - sum_1) ;
        return query(mid + 1 , sum , right) ;
    }
    else if(pos > mid)
    return query(pos , sum , right) ;
}
int main()
{
    //freopen("in.txt" ,"r" ,stdin) ;
    int T ;
    scanf("%d" , &T) ;
    while(T--)
    {
        int  n , m  ;
        scanf("%d%d" , &n , &m) ;
        build(1 , n , 1) ;
        int K , A , F ;
        while(m--)
        {
            scanf("%d%d%d" ,&K , &A , &F ) ;
            if(K == 1)
            {
                int sum = F ;
                int temp ;int ans_l , ans_r ;
                int sum_r = getsum(A+1, n , 1) ;
                if(sum_r == 0)puts("Can not put any one.");
                else
                {
                    sum = (sum_r > F) ? F : sum_r ;
                    ans_r = query(A+1 ,  sum , 1) ;
                    sum = 1;
                    ans_l = query(A+1 , sum, 1) ;
                    printf("%d %d\n", ans_l - 1 , ans_r - 1) ;
                    update(ans_l , ans_r , 0 , 1) ;
                }
            }
            if(K == 2)
            printf("%d\n" , update(A+1 , F+1 , 1 , 1)) ;
        }
        puts("") ;
    }
    return 0 ;
}













































































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值