Vases and Flowers HDU - 4614 线段树 + 二分

传送门
题意:编号为 0 ~ n - 1 个花瓶,有两个操作
(1)以 a 为起点,选择之后的 k 个花瓶放上花,输出左右端点。
(2)清空 l ~ r 的所有花瓶中的花,输出清除的花数量
对于第二个操作就是线段树区间赋值和区间查询了。
第一个操作如果知道左右端点直接区间赋值即可。现在问题是怎么求左右端点。比较显然可以在线段树上进行二分,分别二分出来第一个数位置和最后一个数位置。如果填不满k个的话显然第二个答案是INF,不会被更新。那么就需要把k改成 l ~ n - 1 中空花瓶个数,再二分一次就行了。

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define pb push_back
#define mk make_pair
using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n,m;
struct Node
{
    int l,r;
    int sum,lazy;
}tr[N<<2];

void pushup(int u)
{
    tr[u].sum=tr[L].sum+tr[R].sum;
}

void pushdown(int u)
{
    if(tr[u].lazy==-1) return;
    tr[L].lazy=tr[R].lazy=tr[u].lazy;
    tr[L].sum=Len(L)*tr[u].lazy;
    tr[R].sum=Len(R)*tr[u].lazy;
    tr[u].lazy=-1;
}

void build(int u,int l,int r)
{
    tr[u]={l,r,0,-1};
    if(l==r)
    {
        tr[u].sum=1;
        return;
    }
    build(L,l,Mid),build(R,Mid+1,r);
    pushup(u);
}

void modify(int u,int l,int r,int c)
{
    if(tr[u].l>=l&&tr[u].r<=r)
    {
        tr[u].sum=Len(u)*c;
        tr[u].lazy=c;
        return;
    }
    pushdown(u);
    if(l<=Mid) modify(L,l,r,c);
    if(r>Mid) modify(R,l,r,c);
    pushup(u);
}

int query(int u,int l,int r)
{
    if(tr[u].l>=l&&tr[u].r<=r) return tr[u].sum;
    pushdown(u);
    int ans=0;
    if(l<=Mid) ans+=query(L,l,r);
    if(r>Mid) ans+=query(R,l,r);
    return ans;
}

void solve(int LL,int C)
{
    int l=LL,r=n-1,ans1=INF,ans2=INF;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(query(1,l,mid)>=1) r=mid-1,ans1=mid;
        else l=mid+1;
    }
    l=LL,r=n-1;
    while(l<=r)
    {
        int mid=l+r>>1;
        int c=query(1,l,mid);
        if(c>=C) r=mid-1,ans2=mid;
        else C-=c,l=mid+1;
    }
    if(ans1==INF&&ans2==INF) puts("Can not put any one.");
    else
    {
        if(ans2==INF)
        {
            C=query(1,LL,n-1);
            l=LL,r=n-1;
            while(l<=r)
            {
                int mid=l+r>>1;
                int c=query(1,l,mid);
                if(c>=C) r=mid-1,ans2=mid;
                else C-=c,l=mid+1;
            }
        }
        printf("%d %d\n",ans1,ans2);
        modify(1,ans1,ans2,0);
    }
}
//0 1 2 3 4 5 6 7 8 9
//0 0 1 1 1 1 0 0 0 0
int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    int _; scanf("%d",&_); int T=0;
    while(_--)
    {
        scanf("%d%d",&n,&m);
        build(1,0,n-1);
        while(m--)
        {
            int op,l,r; scanf("%d%d%d",&op,&l,&r);
            if(op==1) solve(l,r);
            else
            {
                printf("%d\n",r-l+1-query(1,l,r));
                modify(1,l,r,1);
            }
        }
        puts("");
    }




	return 0;
}
/*

*/









猜你喜欢

转载自blog.csdn.net/DaNIelLAk/article/details/108302895
今日推荐