hdu 4614 Vases and Flowers

题意:给定一个区间[0,N-1],初始时每个位置上的数字都是0,有两种操作,1.在位置A开始寻找F(如果没有这么多,则有多少个就找多少个)个数值为0的位置,把位置上的数修改为1,并返回第一个和最后一个修改的位置。2.查询区间[A,B]内1的个数,并把区间[A,B]每个位置上的数修改为0。

        对于操作2,直接应用区间更新的懒操作就可以了,而对于操作1,我们可以查询上区间[0,A-1]里有多少有值为0的数,定义其为cnt,然后在整个线段树里查询cnt+1个值为0的数在哪里,同理查询cnt+F个空的瓶子在哪里,这就得到了其对应的起点和终点了。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))

const int N=60005;

struct node
{
    int lft,rht;
    int cnt,delay;
    int mid(){return MID(lft,rht);}

    void fun(int valu)
    {
        delay=valu;
        if(valu>0) cnt=0;
        else cnt=rht-lft+1;
    }
    void init(){ cnt=rht-lft+1; delay=0; }
};
struct Segtree
{
    node tree[N*4];
    void PushDown(int ind)
    {
        if(tree[ind].delay)
        {
            tree[LL(ind)].fun(tree[ind].delay);
            tree[RR(ind)].fun(tree[ind].delay);
            tree[ind].delay=0;
        }
    }
    void PushUp(int ind)
    {
        tree[ind].cnt=tree[LL(ind)].cnt+tree[RR(ind)].cnt;
    }
    void build(int lft,int rht,int ind)
    {
        tree[ind].lft=lft;    tree[ind].rht=rht;
        tree[ind].init();
        if(lft!=rht)
        {
            int mid=tree[ind].mid();
            build(lft,mid,LL(ind));
            build(mid+1,rht,RR(ind));
        }
    }
    void updata(int st,int ed,int valu,int ind)
    {
        int lft=tree[ind].lft,rht=tree[ind].rht;
        if(st<=lft&&rht<=ed) tree[ind].fun(valu);
        else
        {
            PushDown(ind);
            int mid=tree[ind].mid();
            if(st<=mid) updata(st,ed,valu,LL(ind));
            if(ed> mid) updata(st,ed,valu,RR(ind));
            PushUp(ind);
        }
    }
    int query(int st,int ed,int ind)
    {
        int lft=tree[ind].lft,rht=tree[ind].rht;
        if(st<=lft&&rht<=ed) return tree[ind].cnt;
        else
        {
            PushDown(ind);
            int mid=tree[ind].mid();
            int cnt1=0,cnt2=0;
            if(st<=mid) cnt1=query(st,ed,LL(ind));
            if(ed> mid) cnt2=query(st,ed,RR(ind));
            PushUp(ind);
            return cnt1+cnt2;
        }
    }
    int findPos(int st,int ed,int valu,int ind)
    {
        int lft=tree[ind].lft,rht=tree[ind].rht;
        if(lft==rht) return lft;
        else
        {
            PushDown(ind);
            int mid=tree[ind].mid(),pos;
            if(ed<=mid) pos=findPos(st,ed,valu,LL(ind));
            else if(st>mid) pos=findPos(st,ed,valu,RR(ind));
            else
            {
                if(tree[LL(ind)].cnt>=valu) pos=findPos(st,ed,valu,LL(ind));
                else pos=findPos(st,ed,valu-tree[LL(ind)].cnt,RR(ind));
            }
            PushUp(ind);
            return pos;
        }
    }
}seg;
int main()
{
    //freopen("04.in","r",stdin);

    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m; scanf("%d%d",&n,&m);

        seg.build(0,n-1,1);
        for(int i=0;i<m;i++)
        {
            int a,b,c; scanf("%d%d%d",&a,&b,&c);
            if(a==1)
            {
                int tmp=seg.query(b,n-1,1);
                b=min(b,n-1);
                if(tmp==0)
                {
                    puts("Can not put any one.");
                    continue;
                }
                else if(tmp<=c) c=tmp;

                int sum=0;
                if(b-1>=0) sum=seg.query(0,b-1,1);
                int pos1=seg.findPos(0,n-1,sum+1,1);
                int pos2=seg.findPos(0,n-1,c+sum,1);

                seg.updata(pos1,pos2,1,1);
                printf("%d %d\n",pos1,pos2);
            }
            else
            {
                b=min(b,n-1); c=min(c,n-1);
                int sum=seg.query(b,c,1);
                seg.updata(b,c,-1,1);
                printf("%d\n",c-b+1-sum);
            }
        }
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值