Problem Link

有一棵 \(n\) 个点的完全二叉树(点 \(i\) 的父亲是 \(\lfloor i/2\rfloor\)),第 \(i\) 个点有 \(a_i\) 个苹果。现在有 \(m\) 个订单,每个订单只接受 \(u_i\) 到 \(v_i\) 路径上的苹果,保证 \(u_i\) 是 \(v_i\) 的祖先,并且最多只接受 \(c_i\) 个苹果,单价为 \(w_i\)。你可以把苹果任意分给订单,求最大可能收益。

\(n,m\le 5\times 10^5\)。


技巧:费用流转 Hall 定理

我会费用流!直接从每个订单向链上的点连边,源点向订单连容量为订单上限,费用为单价的边,点向汇点连容量为苹果数的边,跑最大费用流即可!\(m\log n\) 条边,这不乱冲

当然冲不过去。考虑模拟费用流(说白了就是贪心,但是由费用流可以清楚地证明正确性),即将所有订单按单价从大到小排序,每次流的时候尽量流满即可(注意到反向边没法流)。

怎么流呢?是一个比较清奇的想法:二分一个流量,然后用别的方法判断当前流量是否合法。具体地,我们可以使用 Hall 定理!

发现给每条边钦定好流量之后,判断合不合法,就是判断是否存在一个链到苹果的匹配(前者满配),对应到 Hall 定理就是是否对于任意多条链的并,它们对应位置上的苹果数之和大于等于这些链的需求之和。

进一步,若干条链的并形成若干个连通块,显然不同连通块可以分开算。

于是考虑枚举这个连通块的根 \(r\),那么就是看是否存在一个以 \(r\) 为根的连通块,其中链和大于苹果和则不合法。可以对于每条链 \((u,v)\) 满足 \(u\) 在 \(r\) 的子树内,在 \(v\) 上打一个 \(-c_i\) 的标记,对每个节点打一个 \(+a_i\) 的标记,那么合法当且仅当每个包含根的连通块权值和均 \(\ge 0\)。这个可以用一个简单的 dp 判断:每个 \(f\) 从子树之和转移过来,然后对 \(0\) 取 \(\min\)。

修改一条链只用判断它的 \(v\) 到 \(1\) 路径上的那些根是否合法,每个根也只用重新计算 \(v\) 祖先里的那些点,所以单次时间复杂度 \(O(\log^2 n)\),总复杂度(算上二分)\(O(m\log^3 n)\)。

过不去!然后发现这个二分完全没必要,对于每个根可以直接算出所允许的最大值取个 \(\min\) 即可。

具体地,在 \(v\) 不断往上更新时,如果发现当前节点的 \(f\) 大于 \(0\),则可以在此时将链选的权值 \(x\) 增加 \(f\)。理由是反正 \(f\) 都要对 \(0\) 取 \(\min\),并且如果 \(f\le 0\),那增大 \(x\) 必然减小 \(f\),欠的总是要还的,不如将来再加。

这样总时间复杂度就 \(O(m\log^2 n)\) 了。

点击查看代码
#include <bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Rev(i,a,b) for(int i=a;i>=b;i--)
#define Fin(file) freopen(file,"r",stdin);
#define Fout(file) freopen(file,"w",stdout);
using namespace std;
const int N=1e5+5; typedef long long ll;
struct Node{int u,v,c,w;bool operator<(const Node& rhs)const{return w>rhs.w;}}O[N];;
int n,m,a[N]; ll f[N][18],g[N][18];
ll work(int o,int v){
ll res=0; int z=__lg(o);
for(int k=v;k>=o;k>>=1){
int k1=k<<1,k2=k<<1|1; k1>n&&(k1=0); k2>n&&(k2=0);
res+=max(0ll,f[k1][z]+f[k2][z]+a[k]-g[k][z]);
}
return res;
}
void update(int o,int v,ll x){
int z=__lg(o); g[v][z]+=x;
for(int k=v;k>=o;k>>=1){
int k1=k<<1,k2=k<<1|1; k1>n&&(k1=0); k2>n&&(k2=0);
f[k][z]=min(0ll,f[k1][z]+f[k2][z]+a[k]-g[k][z]);
}
assert(f[o][z]>=0);
}
void solve(){
cin>>n>>m; For(i,1,n) cin>>a[i];;
For(i,0,n) memset(f[i],0,sizeof(f[i])),memset(g[i],0,sizeof(g[i]));
For(i,1,m) cin>>O[i].u>>O[i].v>>O[i].c>>O[i].w;; sort(O+1,O+1+m);
ll ans=0;
For(i,1,m){
auto [u,v,c,w]=O[i];
ll x=c; for(int o=u;o;o>>=1) x=min(x,work(o,v));
ans+=x*w; for(int o=u;o;o>>=1) update(o,v,x);
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
int T; cin>>T; while(T--) solve();
return 0;
}

【网络流,dp】Gym102220A Apple Business的更多相关文章

  1. 【树形dp】Apple Tree

    [poj2486]Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10800   Accepted: 3 ...

  2. POJ3176-基础DP

    很基础的dp题.有一头奶牛想接尽量多的苹果,有w此移动机会. dp[i][w] = max(dp[i-1][w+1] + 能否吃到苹果 ,dp[i-1][w] + 能否吃到苹果)  //从上一分钟是否 ...

  3. The 13th Chinese Northeast Collegiate Programming Contest

    题解: solution Code: A. Apple Business #include<cstdio> #include<algorithm> #include<ve ...

  4. QDEZ集训笔记【更新中】

    这是一个绝妙的比喻,如果青岛二中的台阶上每级站一只平度一中的猫,差不多站满了吧 自己的理解 [2016-12-31] [主席树] http://www.cnblogs.com/candy99/p/61 ...

  5. 较具体的介绍JNI

    JNI事实上是Java Native Interface的简称,也就是java本地接口.它提供了若干的API实现了和Java和其它语言的通信(主要是C&C++).或许不少人认为Java已经足够 ...

  6. 更具体的描述JNI

    JNI事实上,Java Native Interface缩写,也就是说,java本地接口. 它提供了许多API实现和Java并与其他语言的沟通(主要C&C++). 也许很多人认为Java够劲. ...

  7. POJ2385--Apple Catching(动态规划)

    It is a little known fact that cows love apples. Farmer John has two apple trees (which are convenie ...

  8. 较详细的介绍JNI

    JNI其实是Java Native Interface的简称,也就是java本地接口.它提供了若干的API实现了和Java和其他语言的通信(主要是C&C++).也许不少人觉得Java已经足够强 ...

  9. BZOJ 1221: [HNOI2001] 软件开发【最小费用最大流】

    Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...

  10. Distributing Custom Apps

    Distributing Custom Apps 分配自定义应用程序 November 10, 2020 2020年11月10日 Custom apps let you meet the unique ...

随机推荐

  1. 经典永流传,华为云媒体 AI 让老电影焕发新生

    摘要:近日,在华为云TechWave全球技术峰会(人工智能&数据)上,马栏山视频文创产业园首席专家周苏岳受邀发表演讲<经典永流传,媒体 AI 让老电影焕发新生>,分享与华为云原生媒 ...

  2. 火山引擎DataLeap的Catalog系统搜索实践(一):背景与功能需求

    火山引擎DataLeap的Data Catalog系统通过汇总和组织各种元数据,解决了数据生产者梳理数据.数据消费者找数和理解数的业务场景,其中搜索是Data Catalog的主要功能之一.本文详细介 ...

  3. Jenkins Pipeline 多分支流水线 Input length = 1

    Jenkins 多分支流水线 构建过程中报错. [Pipeline] // node [Pipeline] End of Pipeline java.nio.charset.MalformedInpu ...

  4. Vue项目部署Nginx后,刷新页面出现404问题

    在Nginx配置文件nginx.conf中加入如下配置.(index.html根据实际页面配置) 增加:try_files $uri $uri/ /index.html; #解决页面刷新404问题 s ...

  5. drf-Response drf-request.data 序列化类的使用 反序列化新增、修改、删除数据

    目录 APIView基本使用 使用原生Django写接口(View + JsonResponse) 使用drf写接口(APIView + drf Response) drf 两种导入View的方式 d ...

  6. MAC SAP for JAVA配置

    一.自定义应用程序服务器配置 conn = /H/<SAP路由器服务器地址(如果有)>/S/3299 /H/<SAP服务器地址>/S/32<Instance_no> ...

  7. HashMap非线程安全到底有什么问题

    HashMap是Java中常用的数据结构,用于存储键值对,并且提供了快速的查找和插入操作.下面挖掘一下HashMap内部的架构设计思维: 哈希函数的设计: HashMap使用哈希函数将键映射到数组索引 ...

  8. 开发人员常用Docker指令

    什么是 Docker? Docker 是一个开源的容器化平台,用于构建.打包和运行应用程序.它允许开发者将应用程序及其依赖项打包成一个独立的可移植容器,可以在任何环境中运行,无论是开发环境.测试环境还 ...

  9. C#将日期格式化为指定格式

    private void btn_GetTime_Click(object sender, EventArgs e) { lab_time.Text = DateTime.Now.ToString(& ...

  10. Ubuntu安装jdk的步骤

    .markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...