hdu-4614-Vases and Flowers(线段树,区间更新区间查询,lazy,二分)

来源:互联网 发布:php日志系统设计 编辑:程序博客网 时间:2024/04/26 16:57

Problem Description
  Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, ..., N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.
 

Input
  The first line contains an integer T, indicating the number of test cases.
  For each test case, the first line contains two integers N(1 < N < 50001) and M(1 < M < 50001). N is the number of vases, and M is the operations of Alice. Each of the next M lines contains three integers. The first integer of one line is K(1 or 2). If K is 1, then two integers A and F follow. It means Alice receive F flowers and try to put a flower in the vase A first. If K is 2, then two integers A and B follow. It means the owner would like to clean the vases numbered from A to B(A <= B).
 

Output
  For each operation of which K is 1, output the position of the vase in which Alice put the first flower and last one, separated by a blank. If she can not put any one, then output 'Can not put any one.'. For each operation of which K is 2, output the number of discarded flowers. 
  Output one blank line after each test case.
 

Sample Input
210 51 3 52 4 51 1 82 3 61 8 810 61 2 52 3 41 0 82 2 51 4 41 2 3
 

Sample Output
3 721 94Can not put any one.2 620 944 52 3

不错的题目,题意是0~n-1代表花瓶,操作1:从a开始往后找f个空花瓶插花,插不了的花扔掉;操作2:把从a~b的花瓶置空

线段叶节点为1代表是空花瓶,为0代表有花,则tree[i]代表区间内的空瓶数,

对于操作1:二分找到从a起第一个能插的花瓶下标,和最后一个要插的花瓶下标,然后更新区间

操作2:线段树直接query求出区间内空花瓶数,用总花瓶数减之就是有花的数量,然后更新区间

代码:

#include<iostream>#include<string>#include<cstdio>#include<algorithm>#include<cmath>#include<iomanip>#include<queue>#include<cstring>#include<map>using namespace std;typedef long long ll;#define M 50010#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int n,m,k,a,b;int num;int tree[M<<2],col[M<<2]; //col为1代表需要置空,为0代表需要插入,为-1代表没有进程inline void pushdown(int rt,int x){    if(col[rt]==0) //整个父区间全部插上花,    {        col[rt<<1]=col[rt<<1|1]=0; //则子区间也全部插上        tree[rt<<1]=tree[rt<<1|1]=0;//子区间内一个空花瓶也没有        col[rt]=-1;    }    else if(col[rt]==1) //父区间去不置空    {        col[rt<<1]=col[rt<<1|1]=1; //子区间全部置空        tree[rt<<1]=x-(x>>1); //子区间都是空花瓶        tree[rt<<1|1]=x>>1;        col[rt]=-1;    }}void build(int l,int r,int rt){    tree[rt]=1; //初始化为空    col[rt]=-1;    if(l==r)    {        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);    tree[rt]=tree[rt<<1]+tree[rt<<1|1];}void update(int ql,int qr,int v,int l,int r,int rt){    if(ql<=l&&qr>=r)    {        col[rt]=v;        if(v) //置空            tree[rt]=r-l+1;        else  //插满            tree[rt]=0;        return;    }    pushdown(rt,r-l+1); //用父区间更新子区间    int m=(l+r)>>1;    if(ql<=m)        update(ql,qr,v,lson);    if(qr>m)        update(ql,qr,v,rson);    tree[rt]=tree[rt<<1]+tree[rt<<1|1];}int query(int ql,int qr,int l,int r,int rt){    if(ql<=l&&qr>=r)    {        return tree[rt];    }    pushdown(rt,r-l+1);    int m=(l+r)>>1;    int ret=0;    if(ql<=m)        ret+=query(ql,qr,lson);    if(qr>m)        ret+=query(ql,qr,rson);    tree[rt]=tree[rt<<1]+tree[rt<<1|1]; //虽然只是查询,因为上面有pushdown更新了子区间,所以要pushup    return ret;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        build(0,n-1,1);        while(m--)        {            scanf("%d%d%d",&k,&a,&b);            if(k==1)            {                num=query(a,n-1,0,n-1,1);                if(num==0) //区间内没有空花瓶                {                    printf("Can not put any one.\n");                    continue;                }                if(num<b) //空花瓶数量有限的话,就插入几个                    b=num;                int ll=a,rr=n-1,mid;                while(ll<=rr)                {                    mid=(ll+rr)>>1;                    if(query(a,mid,0,n-1,1)>=1)                        rr=mid-1;                    else                        ll=mid+1;                }                int ansl,ansr;                ansl=ll; //第一个能插的花瓶下标                ll=a;rr=n-1;                while(ll<=rr)                {                    mid=(ll+rr)>>1;                    if(query(a,mid,0,n-1,1)>=b)                        rr=mid-1;                    else                        ll=mid+1;                }                ansr=ll; //最后一个要插的花瓶下标                printf("%d %d\n",ansl,ansr);                update(ansl,ansr,0,0,n-1,1);            }            else            {                printf("%d\n",b-a+1-query(a,b,0,n-1,1));                update(a,b,1,0,n-1,1);            }        }        printf("\n");    }    return 0;}


阅读全文
0 0
原创粉丝点击