P2460清理花瓶

问题描述

Nicole是大家心中的女神,她每天都会收到很多束男生们送的鲜花。她有N个花瓶,编号0到N-1.
每天她都会试着把收到的花束放到花瓶里,一个花瓶只能装一束花。她总是随机地选择一个花瓶A,如果该花瓶是空的,她就放一束花在里面,否则她会跳过这个花瓶。接着她会试着往A+1,A+2,…,N-1号花瓶里面放花,直到没有花了或者是第N-1号花瓶都被讨论了。然后她会扔掉剩下的花。
有时Nicole也会去清理花瓶,因为花瓶太多了,所以她每次都随机选择一段花瓶清理。比如编号A到编号B这一段花瓶,她会把里面的花全都扔掉。

输入格式

第一行,两个整数N和M,表示花瓶的个数和操作的次数
接下来M行,每行三个整数K,A,B。
若K=1,表示今天Nicole收到了B束花,她打算从第A号花瓶开始放花。
若K=2,表示今天Nicole要清理花瓶,她打算清理掉从第A号到第B号花瓶里的花(A <= B)。

输出格式

对于每次操作,输出一行结果:
若K=1,输出Nicole放花的起止花瓶的编号。若一束花也放不进去,输出 “Can not put any one.”
若k=2,输出Nicole清理掉的花的数目。

样例输入

输入样例1
10 5
1 3 5
2 4 5
1 1 8
2 3 6
1 8 8

输入样例2
10 6
1 2 5
2 3 4
1 0 8
2 2 5
1 4 4
1 2 3

样例输出

输出样例1
3 7
2
1 9
4
Can not put any one.

输出样例2
2 6
2
0 9
4
4 5
2 3

提示

1 < N < 50001
1 < M < 50001

题解

线段树加二分查找
注意二分查找边界(手推小数据)

代码

#include<stdio.h>   
#include<cstring>   
#include<algorithm>   
#include<iostream>   
#include<cmath>   
#include<cstring>   
#include<queue>   
using namespace std;   
#define maxn 1e9   
#define pr cout<<//lazy 修改下一层值并延续标记  
#define inf 50005//下放的意义为修改下一层的数值   
int n,m;  
struct node{        
    int a,b,x,lazy;   
};   
node tree[inf*5];   
void bt (int p,int x,int y)   
{   
    int mid=x+y>>1;   
    tree[p].a=x;tree[p].b=y;   
    if(x==y) return;   
    bt(p<<1,x,mid);   
    bt(p<<1|1,mid+1,y);   
}   
void pd(int k)   
{  
    tree[k<<1].lazy=tree[k].lazy;  
    tree[k<<1|1].lazy=tree[k].lazy;  
    if(tree[k].lazy==1){  

tree[k<<1].x=tree[k<<1].b-tree[k<<1].a+1;  
        tree[k<<1|1].x=tree[k<<1|1].b-tree[k<<1|1].a+1;  
    }  
    if(tree[k].lazy==2){  
        tree[k<<1].x=tree[k<<1|1].x=0; 
    }  
    tree[k].lazy=0;  
}  
void add(int p,int x,int y){  
    if(tree[p].lazy) pd(p);  
    if(tree[p].a>=x&&tree[p].b<=y)  
    {  
        tree[p].x=tree[p].b-tree[p].a+1; 
        tree[p].lazy=1;  
        return;  
    }  
     int mid=tree[p].a+tree[p].b>>1;  
     if(mid>=x) add(p<<1,x,y);  
     if(mid<y) add(p<<1|1,x,y);  
     tree[p].x=tree[p<<1].x+tree[p<<1|1].x;  
}  
int cl(int p,int x,int y){  
    if(tree[p].lazy) pd(p);  
    if(tree[p].a>=x&&tree[p].b<=y)  
    {  
        int t=tree[p].x;  
        tree[p].x=0;  
        tree[p].lazy=2;  
        return t;  
     }  
     int mid=tree[p].a+tree[p].b>>1;  
     int t1=0,t2=0;
     if(mid>=x) t1=cl(p<<1,x,y);  
     if(mid<y) t2=cl(p<<1|1,x,y);  
     tree[p].x=tree[p<<1].x+tree[p<<1|1].x;  
    return t1+t2;
}  
int ask(int p,int x,int y){  
    if(tree[p].lazy) pd(p);  
    if(tree[p].a>=x&&tree[p].b<=y) return tree[p].x; 
    int l1=0,r1=0,mid=tree[p].a+tree[p].b>>1; 
    if(mid>=x) l1=ask(p<<1,x,y);  
    if(mid<y) r1=ask(p<<1|1,x,y);

    return l1+r1;  
}  
int b1(int x,int y)  
{  
    int l=x,r=n;  
    while(l<=r){  
        int mid=(l+r)>>1; 
        if(mid-x+1-ask(1,x,mid)>=y) r=mid-1;  
        else l=mid+1;  
    }  

    return l; 
}  
int b2(int x,int y)  
{  
    int l=1,r=x;  
    while(l<=r){  

        int mid=(l+r)>>1;  
        if(x-mid+1-ask(1,mid,x)>=y) l=mid+1;  
        else r=mid-1;  
    }  
    return r; 
}  
int main()   
{   
     int i,j;  
     scanf("%d%d",&n,&m);  
     int x,y,z;  
     bt(1,1,n);  
     for(i=1;i<=m;i++){  
         scanf("%d%d%d",&x,&y,&z);  
         if(x==1){  
             y++;  
             int t=n-y+1-ask(1,y,n);
             if(t==0){ 
                 cout<<"Can not put any one."<<endl;  
             }  
             else{  
                 z=min(z,t);  
                 int en=b1(y,z);  
                 int st=b2(en,z);  
                 cout<<st-1<<" "<<en-1<<endl;  
                 add(1,st,en);  
             }  
            }  
         else{  
             y++;z++;
             cout<<cl(1,y,z)<<endl;  
         }  
     }  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值