HDU 4614 Vases and Flowers 解题报告

题目

题意:一开始有标号为0~N-1的N个空花瓶,进行两种操作

操作1:A F,从标号为A的花瓶开始往后面放F朵花,如果当前花瓶有花了,就继续往后放,如果有花没有地方放了就丢掉。输出第一朵花和最后一朵花放的花瓶标号

操作2:A B,将花瓶A~B全部清空,并输出多少个花瓶被清空。

解法:

利用线段树的区间更新区间查询,线段树存储区间内有多少不为空的花瓶

对于操作1,先在[A,N-1]二分起点,再根据起点s二分[s,N-1]终点,要注意可能放不下所有的花的情况。

也可以在线段树上增加参数不用二分终点,会快很多。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 50005

int n,m;
int tree[maxn<<2],lazy[maxn<<2];
void down(int p,int la,int l,int r)
{
    int mid=(l+r)>>1;
    if (la==-1) return;
    lazy[p<<1]=la;
    lazy[p<<1|1]=la;
    tree[p<<1]=la*(mid-l+1);
    tree[p<<1|1]=la*(r-mid);
    lazy[p]=-1;
}
void insert(int p,int L,int R,int l,int r,int flag)
{
    if (l==L&&r==R)
    {
        tree[p]=flag*(R-L+1);
        lazy[p]=flag;
        return;
    }
    down(p,lazy[p],L,R);
    int mid=(L+R)>>1;
    if (r<=mid) insert(p<<1,L,mid,l,r,flag);
    else if (l>mid) insert(p<<1|1,mid+1,R,l,r,flag);
    else
    {
        insert(p<<1,L,mid,l,mid,flag);
        insert(p<<1|1,mid+1,R,mid+1,r,flag);
    }
    tree[p]=tree[p<<1]+tree[p<<1|1];
}
int cal(int p,int L,int R,int l,int r)
{
    if (l==L&&r==R) return tree[p];
    down(p,lazy[p],L,R);
    int mid=(L+R)>>1,res;
    if (r<=mid) res=cal(p<<1,L,mid,l,r);
    else if (l>mid) res=cal(p<<1|1,mid+1,R,l,r);
    else res=cal(p<<1,L,mid,l,mid)+cal(p<<1|1,mid+1,R,mid+1,r);
    tree[p]=tree[p<<1]+tree[p<<1|1];
    return res;
}
int main()
{
    int cas,d,a,b;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%d%d",&n,&m);
        memset(tree,0,sizeof(tree));
        memset(lazy,-1,sizeof(lazy));
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&d,&a,&b);
            if (d==1)
            {
                int l=a+1,r=n;
                int s=-1,t=-1;
                while (l<=r)
                {
                    int mid=(l+r)>>1;
                    if (cal(1,1,n,a+1,mid)==mid-a) l=mid+1;
                    else r=mid-1,s=mid;
                }
                if (s==-1){printf("Can not put any one.\n");continue;}
                l=s,r=n;
                b=min(b,n-s+1-cal(1,1,n,s,n));
                while (l<=r)
                {
                    int mid=(l+r)>>1;
                    if (mid-s+1-cal(1,1,n,s,mid)>=b) t=mid,r=mid-1;
                    else l=mid+1;
                }
                printf("%d %d\n",s-1,t-1);
                insert(1,1,n,s,t,1);
            }
            else
            {
                int tmp=cal(1,1,n,a+1,b+1);
                insert(1,1,n,a+1,b+1,0);
                printf("%d\n",tmp);
            }
        }
        printf("\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值