[bzoj5142][Usaco2017 Dec]Haybale Feast

Orz w_yqts
在某王姓dalao的指导下暂时卡到rank1……Orz
二分答案

#include <cstdio>
#define ll long long
#define N 100001
inline int read()
{
    char ch=getchar();
    int x=0;
    while ('0'>ch || ch>'9') ch=getchar();
    while ('0'<=ch && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}
ll m;
int a[N],b[N],n,l=0,r=1e9,mid;
inline bool check()
{
    ll t=0LL;
    for (int i=1;i<=n;++i)
    {
        if (b[i]>mid) {t=0;continue;}
        t+=a[i];
        if (t>=m) return 1;
    }
    return 0;
}
int main()
{
    n=read();scanf("%lld",&m);
    for (int i=1;i<=n;++i) a[i]=read(),b[i]=read();
    while (l<r)
    {
        mid=(l+r)>>1;
        if (check()) r=mid;else l=mid+1;
    }
    printf("%d\n",l);
}

并查集合并

#include <cstdio>
#include <algorithm>
#define ll long long
#define N 100001
inline int read()
{
    char ch=getchar();
    int x=0;
    while ('0'>ch || ch>'9') ch=getchar();
    while ('0'<=ch && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}
struct node
{
    int x,y,id;
}a[N];
bool cmp(node x,node y)
{
    return x.y<y.y;
}
ll m,s[N];
int f[N],n,flag[N];
inline int find(int x)
{
    if (f[x]==x) return x;
    f[x]=find(f[x]);
    return f[x];
}
inline void merge(int x,int y)
{
    x=find(x);y=find(y);
    s[x]+=s[y];
    f[y]=x;
}
int main()
{
    n=read();scanf("%lld",&m);
    for (int i=1;i<=n;++i) a[i]={read(),read()},a[i].id=f[i]=i,s[i]=a[i].x;
    std::sort(a+1,a+1+n,cmp);
    for (int i=1;i<=n;++i)
    {
        int id=a[i].id;
        flag[id]=1;
        if (flag[id-1]) merge(id,id-1);
        if (flag[id+1]) merge(id,id+1);
        if (s[find(id)]>=m) {printf("%d\n",a[i].y);return 0;}
    }
}

单调队列

#include <cstdio>
#define ll long long
#define N 100005
inline int read()
{
    char ch=getchar();
    int x=0;
    while ('0'>ch || ch>'9') ch=getchar();
    while ('0'<=ch && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}
inline int min(int x,int y)
{
    return x<y?x:y;
}
ll m,s;
int a[N],b[N],q[N],n,ans=1e9;
int main()
{
    n=read();scanf("%lld",&m);
    for (int i=1;i<=n;++i) a[i]=read(),b[i]=read();
    int last=0,st=1,ed=0;
    for (int i=1;i<=n;++i)
    {
        while (st<=ed && q[st]<i) ++st;
        s-=a[i-1];
        while (s<m && last<n)
        {
            s+=a[++last];
            while (b[last]>=b[q[ed]] && st<=ed) --ed;
            q[++ed]=last;
        }
        if (s<m) break;
        ans=min(ans,b[q[st]]);
    }
    printf("%d\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值