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. Spring Cache设计之美,你品,你细品…

    摘要:Spring Cache的功能很强大,设计也非常优雅,特别适合缓存控制没有那么细致的场景,比如门户首页,偏静态展示页面,榜单等等 本文分享自华为云社区<品味 spring cache设计之 ...

  2. 基于DMS的数仓智能运维服务,知多少?

    摘要:GaussDB(DWS)使用DMS来承载数据库的智能运维体系,提供了数据库运维过程中的监控,分析,处理三大核心处理过程. 本文分享自华为云社区<GaussDB(DWS) 数据库智能监控运维 ...

  3. nginx网站限速限流配置——网站被频繁攻击,nginx上的设置limit_req和limit_conn

    利用ngx_http_limit_req_module模块,可根据键值(如ip)限制每分钟的速率: limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "l ...

  4. 开心档之MySQL 导出数据

    MySQL 导出数据 MySQL中你可以使用SELECT...INTO OUTFILE语句来简单的导出数据到文本文件上. 使用 SELECT ... INTO OUTFILE 语句导出数据 以下实例中 ...

  5. Jenkins Pipeline 流水线 - 拉代码(SVN) + Maven 编译打包

    Jenkins Pipeline 流水线 步骤 拉取SVN代码 -> Maven 构建 -> Docker 编译 -> 发布至阿里云仓库 -> K8S 更新 Jenkins插件 ...

  6. 股票数据爬虫进阶:免费、开源的股票爬虫Python库,实测真香

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 免费.开源的股票爬虫Python库:Easyquotation 我们在此前的文章中,向大家分享了如何用P ...

  7. 【Flask】Flask快速使用 web框架原理 Flask配置文件写法 路由系统源码分析

    目录 1 Flask介绍 1.1同步框架和异步框架的区别 1.2 flask介绍 2 Flask快速使用 3 web框架原理(了解) 4 flask 展示用户信息案例 4.1 login.html 4 ...

  8. java中类的普通初始化块一定在静态初始化块后运行吗

    大部分教程都会告诉我们静态初始化块和静态字段总是在初始化块和普通类字段前运行,事实上也确实如此,直到我看到下面这样的代码: public class Test { static Test test = ...

  9. Grafana--双Y轴

    grafana版本:6.5.2 背景:同一面板里想展示各实例与集群在一段时间范围内,平均每秒执行命令数,但是由于数值差异太大,曲线图抖动不明显,实例的更近乎于一条直线,所以设置双Y轴,可更直观的展示线 ...

  10. 0x69 图论-二分图的覆盖与独立集

    A:Machine Schedule 输入 5 5 10 0 1 1 1 1 2 2 1 3 3 1 4 4 2 1 5 2 2 6 2 3 7 2 4 8 3 3 9 4 3 0 输出 3 在二分图 ...