[PA2013]Raper
链接:https://www.luogu.com.cn/problem/P4694
题目描述:有个光盘要在天之内加工完毕.有个工厂,每一个光盘要先在工厂加工,再在工厂加工,且第天在工厂,第天在工厂加工的代价为,每一天只能在一个工厂加工,求加工最小代价.
链接:观察题目很像老鼠进洞,考虑先建出费用流模型:
先拆点,考虑连以下几条边:
连,流量为,费用为
,流量为,费用为
,流量为,费用为
对于每一个点,向其右边的对应点连边,流量为,费用为.
观察到以下流:
,即选的的最大对
,即的的最大对,但要选过在左边的与在右边的.
这个可以堆线段树维护,但卡不过.
可以考虑如何将处理掉,使堆模拟费用流时可以调整顺序做,发现是一个关于的凸函数,所以可以二分,然后这时堆模拟费用流就可以静态做了,此时只要一个堆就行了.
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
__int128 res;
long long first=0,ans,last=2e9,mid,k,n,a[500001],b[500001];
int read()
{
char c=0;
int sum=0;
while (c<'0'||c>'9')
c=getchar();
while ('0'<=c&&c<='9')
{
sum=sum*10+c-'0';
c=getchar();
}
return sum;
}
struct reads
{
long long data,op;
bool operator < (const reads &a)const
{
return data>a.data;
}
};
reads tmp;
reads make_reads(long long x,long long y)
{
tmp.data=x;
tmp.op=y;
return tmp;
}
int solve(int p)
{
long long u=0;
reads top;
res=0;
priority_queue<reads>q;
for (int i=1;i<=n;++i)
{
q.push(make_reads(a[i],1));
top=q.top();
q.pop();
if (top.data+b[i]-p>=0)
{
q.push(top);
continue;
}
else
{
res+=(top.data+b[i]-p);
q.push(make_reads(-b[i]+p,0));
u+=top.op;
}
}
return u;
}
int main()
{
n=read(),k=read();
for (int i=1;i<=n;++i)
a[i]=read();
for (int i=1;i<=n;++i)
b[i]=read();
if (k==n)
{
for (int i=1;i<=n;++i)
ans+=(a[i]+b[i]);
printf("%lld\n",ans);
return 0;
}
while (first<=last)
{
mid=(first+last)/2;
if (solve(mid)<=k)
{
first=mid+1;
ans=max(ans,mid);
}
else
last=mid-1;
}
solve(ans);
printf("%lld\n",res+ans*k);
return 0;
}
作者:zhouhuanyi
出处:https://www.cnblogs.com/zhouhuanyi/p/16983708.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!