HDU 4614 Vases and Flowers 线段树

来源:互联网 发布:tomcat启动数据库报错 编辑:程序博客网 时间:2024/06/12 22:25

题意:

         见后文翻译。

思路:

        线段树,查询区间和,修改区间和。根据数据量要求,需要加入 lazy 。

        可插入处标记为 1 ,否则为 0 。

代码:

#include <bits/stdc++.h>using namespace std;#define ls l,mid,rt*2#define rs mid+1,r,rt*2+1#define mi (l+r)/2#define sf l,r,rtconst int MAXN=5e5+500;int tree[MAXN*4],lazy[MAXN*4],upst,upen,st,en,v,n,m,T,x,y,z,ans;bool flag;bool check1(int l,int r,int rt){    if(flag||tree[rt]==0) return 0;    return 1;}bool check2(int l,int r,int rt){    if(tree[rt]==(r-l+1)&&tree[rt]<=v) return 1;    return 0;}void push_down(int l,int r,int rt){    int mid=mi;    if(lazy[rt]==1){        lazy[rt*2]=lazy[rt*2+1]=1;        tree[rt]=r-l+1;        tree[rt*2]=mi-l+1;        tree[rt*2+1]=r-mid;    }    if(lazy[rt]==0){        lazy[rt*2]=lazy[rt*2+1]=0;        tree[rt]=tree[rt*2+1]=tree[rt*2]=0;    }    lazy[rt]=-1;}void push_up(int l,int r,int rt){    tree[rt]=tree[rt*2]+tree[rt*2+1];    if(lazy[rt*2]==lazy[rt*2+1]){        lazy[rt]=lazy[rt*2];        lazy[rt*2]=lazy[rt*2+1]=-1;    }    return ;}void build(int l,int r,int rt){    if(l==r){        tree[rt]=1;lazy[rt]=-1;        return ;    }    int mid=mi;    build(ls);    build(rs);    push_up(sf);    return ;}void update(int l,int r,int rt){    if(st>r||en<l) return ;    push_down(sf);    if(st<=l&&r<=en){        lazy[rt]=v;        if(v==1){            tree[rt]=r-l+1;        }else{            tree[rt]=0;        }        return ;    }    int mid=mi;    update(ls);    update(rs);    push_up(sf);    return ;}int query2(int l,int r,int rt){    if(st>r||en<l) return 0;    push_down(sf);    if(st<=l&&r<=en){        return tree[rt];    }    int mid=mi;    int ans=0;    ans+=query2(ls);    ans+=query2(rs);    push_up(sf);    return ans;}void query1(int l,int r,int rt){    if(st>r||en<l||!check1(sf)) return ;    push_down(sf);    if(st<=l&&r<=en&&check2(sf)){        v-=tree[rt];        ans=r;        if(v==0) flag=1;        return ;    }    int mid=mi;    query1(ls);    query1(rs);    push_up(sf);}int main(){    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        build(1,n,1);        while(m--){            scanf("%d%d%d",&x,&y,&z);            if(x==1){                y++;                st=y;v=1;en=n;ans=-1;flag=0;                query1(1,n,1);                if(ans==-1){                    printf("Can not put any one.\n");                    continue;                }                upst=ans;                v=z;ans=-1;flag=0;                query1(1,n,1);                if(ans==-1) upen=upst;                else upen=ans;                printf("%d %d\n",upst-1,upen-1);                st=upst;en=upen;                v=0;                update(1,n,1);            }else{                y++;z++;                st=y;en=z;v=1;                cout<<(en-st+1)-query2(1,n,1)<<endl;                update(1,n,1);            }            //debug();        }        cout<<endl;    }}

翻译非原创

        Alice有N个花瓶(标号为0~ N-1)。当她收到一些花时,她会随机的选择一个瓶子A,从它开始遍历A,A+1, A+2, ..., N-1号瓶子,遇到空瓶子就放一朵花进去,直到花朵放完或没有瓶子,剩下的花将被丢弃。有时,她也会清理标号从A到B的花瓶(A <= B).花瓶里的花会被丢弃。
Input

  第一行一个整数T,表示数据组数。
  每组数据,第一行一个整数N(1 < N < 50001) and M(1 < M < 50001). N 是花瓶个数,  M是Alice的操作次数. 接下来M行 行3个 整数. 第一个整数 K(1 or 2). 如果K=1, 后面跟两个整数 A 和  F . 表示Alice 得到了F 朵花并且把它们放入从A 的花瓶里. 如果K= 2, 后跟两个整数 A 和  B. 表示Alice  清理的花瓶标号范围(A <= B).

Output

  对于每个K=1的操作,输出第一朵和最后一朵花放置的花瓶标号。如果没有任何放花的位置,输出'Can not put any one.'.对于K=2的操作,输出丢弃花的个数.
   每组数据后输出一个空行.

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 0
原创粉丝点击