【题意】初始有n个空花瓶,然后有q个操作,1 x y,从x开始插花,插够k个即可。2 x y,把x,y区间有有花的花瓶全部清空。

【解题方法】

线段树维护剩余空花瓶的个数

第一种操作二分≥1的最左边的位置,二分≥k的最左边位置
第二种直接更新就好啦
复杂度是O(n+mlog2n)


【AC代码】


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=5e5+5;
int n;
struct Segment{
    int sum[maxn<<2],lazy[maxn<<2];
    void Build(int l,int r,int rt)
    {
        sum[rt]=r-l+1;
        lazy[rt]=-1;
        if(l==r) return ;
        int mid=(l+r)/2;
        Build(l,mid,rt*2);
        Build(mid+1,r,rt*2+1);
    }
    void pushup(int rt){
        sum[rt]=sum[rt*2]+sum[rt*2+1];
    }
    void pushdown(int rt,int m){
        if(lazy[rt]!=-1){
            lazy[rt*2]=lazy[rt*2+1]=lazy[rt];
            sum[rt*2]=lazy[rt]*(m-(m>>1));
            sum[rt*2+1]=lazy[rt]*(m>>1);
            lazy[rt]=-1;
        }
    }
    int update(int L,int R,int v,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            int ret=sum[rt];
            sum[rt]=v*(r-l+1);
            lazy[rt]=v;
            return ret;
        }
        int mid=(l+r)/2;
        pushdown(rt,r-l+1);
        int ret=0;
        if(L<=mid) ret+=update(L,R,v,l,mid,rt*2);
        if(mid<R)  ret+=update(L,R,v,mid+1,r,rt*2+1);
        pushup(rt);
        return ret;
    }
    int queryans(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            return sum[rt];
        }
        pushdown(rt,r-l+1);
        int ret=0;
        int mid=(l+r)/2;
        if(L<=mid) ret+=queryans(L,R,l,mid,rt*2);
        if(mid<R)  ret+=queryans(L,R,mid+1,r,rt*2+1);
        return ret;
    }
}Tree;
int get(int st,int k)
{
    int l=st,r=n;
    while(l<=r){
        int m=(l+r)/2;
        if(Tree.queryans(st,m,1,n,1)>=k) r=m-1;
        else l=m+1;
    }
    return l;
}
int main()
{
    int T,q;
    scanf("%d",&T);
    while(T--)
    {
        int op,x,y;
        scanf("%d%d",&n,&q);
        Tree.Build(1,n,1);
        while(q--)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==1){
                int all=Tree.queryans(x+1,n,1,n,1);
                if(all==0){
                    puts("Can not put any one.");
                }
                else{
                    int l=get(x+1,1);
                    int r=get(x+1,min(all,y));
                    //cout<<l<<" "<<r<<endl;
                    Tree.update(l,r,0,1,n,1);
                    printf("%d %d\n",l-1,r-1);
                }
            }else{
                int tt=Tree.update(x+1,y+1,1,1,n,1);
                int ans=y-x+1-tt;
                printf("%d\n",ans);
            }
        }
        printf("\n");
    }
    return 0;
}