洛谷 P5331 - [SNOI2019]通信(CDQ 分治优化建图+费用流)
首先熟悉网络流的同学应该能一眼看出此题的建模方法:
- 将每个点拆成两个点 \(in_i,out_i\),连一条 \(S\to in_i\),容量为 \(1\) 费用为 \(0\) 的边
- 连一条 \(in_i\to T\) 容量为 \(1\) 费用为 \(W\) 的边,表示哨站 \(i\) 连向控制中心
- 连一条 \(out_i\to T\) 容量为 \(1\) 费用为 \(0\) 的边,表示每个哨站最多被后面一个哨站连接
- 对每对 \(i,j(i>j)\) 连一条 \(in_i\to out_j\) 容量为 \(1\) 费用为 \(|a_i-a_j|\) 的边,表示哨站 \(i\) 连向哨站 \(j\)
然后跑最小费用最大流即可,最大流保证每个哨站都要么连向控制中心,要么连向了前面某个哨站,要么连向了控制中心,最小费用保证费用最小。
然后你兴高采烈地开始码,码好了,测过了样例,交上去……T 了?
不难发现在这个做法中边数最高可达到 \(n^2=10^6\),这显然是费用流所承受不了的。因此考虑优化建边。不过按照传统的线段树优化建图的方法是不太可行的,因为这里既涉及到下标的大小关系 \(i>j\),又涉及到值的大小关系(因为边权中带一个绝对值),也就是说这玩意儿实际上可以视作一个二维偏序,考虑求解 \(k\) 维偏序的时候用到的一个技巧——cdq 分治。每次递归到区间 \([l,r]\) 时候,记 \(mid=\lfloor\dfrac{l+r}{2}\rfloor\),我们就从 \([mid+1,r]\) 向 \([l,mid]\) 连边,我们将 \(a_l,a_{l+1},a_{l+2},\cdots,a_r\) 从小到大排序并去重,假设为 \(b_1,b_2,\cdots,b_m\),我们对每个 \(b_i\) 新建一个虚点 \(pt_i\),然后在 \(pt_i\) 与 \(pt_{i+1}\) 之间连费用为 \(b_{i+1}-b_i\) 的双向边,然后对 \(i\in[l,mid]\) 找出满足 \(b_j=a_i\) 的 \(j\) 然后连 \(pt_j\to out_i\),\(i\in[mid+1,r]\) 也同理,只不过是从 \(in_i\) 向 \(pt_j\) 连边。不难发现这种建图方法与暴力是等价的,边数也降到了 \(n\log n\) 级别,可以通过此题。
这是蒟蒻第一次遇到这种建图方法哦,不喜勿喷~
const int MAXN=1e3;
const int MAXV=2e4;
const int MAXE=1e5*2;
const int INF=0x3f3f3f3f;
int n,W,S=1,T=2,ncnt=2,a[MAXN+5],p1[MAXN+5],p2[MAXN+5];
int hd[MAXV+5],to[MAXE+5],nxt[MAXE+5],cap[MAXE+5],cst[MAXE+5],ec=1;
void adde(int u,int v,int f,int c){
to[++ec]=v;cap[ec]=f;cst[ec]=c;nxt[ec]=hd[u];hd[u]=ec;
to[++ec]=u;cap[ec]=0;cst[ec]=-c;nxt[ec]=hd[v];hd[v]=ec;
} int flw[MAXV+5],pre[MAXV+5],lste[MAXV+5];ll dis[MAXV+5];
bool inq[MAXV+5];
bool getdis(){
memset(dis,63,sizeof(dis));memset(flw,0,sizeof(flw));
dis[S]=0;flw[S]=INF;queue<int> q;q.push(S);inq[S]=1;
while(!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=cap[e],w=cst[e];
if(z&&dis[y]>dis[x]+w){
dis[y]=dis[x]+w;flw[y]=min(flw[x],z);
pre[y]=x;lste[y]=e;
if(!inq[y]){inq[y]=1;q.push(y);}
}
}
} return dis[T]<0x3f3f3f3f3f3f3f3fll;
}
pair<int,ll> mcmf(){
int mxfl=0;ll mncst=0;
while(getdis()){
mxfl+=flw[T];mncst+=flw[T]*dis[T];
for(int i=T;i^S;i=pre[i]){
cap[lste[i]]-=flw[T];cap[lste[i]^1]+=flw[T];
}
} return mp(mxfl,mncst);
}
int b[MAXN+5];
void build(int l,int r){
if(l==r) return;int mid=l+r>>1;
build(l,mid);build(mid+1,r);int cnt=0;
for(int i=l;i<=r;i++) b[++cnt]=a[i];
sort(b+1,b+cnt+1);cnt=unique(b+1,b+cnt+1)-b-1;
for(int i=1;i<cnt;i++){
adde(ncnt+i,ncnt+i+1,INF,b[i+1]-b[i]);
adde(ncnt+i+1,ncnt+i,INF,b[i+1]-b[i]);
}
for(int i=l;i<=r;i++){
int pos=lower_bound(b+1,b+cnt+1,a[i])-b;
if(i>mid) adde(p1[i],ncnt+pos,1,0);
else adde(ncnt+pos,p2[i],1,0);
} ncnt+=cnt;
}
int main(){
scanf("%d%d",&n,&W);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) p1[i]=++ncnt;
for(int i=1;i<=n;i++) p2[i]=++ncnt;
for(int i=1;i<=n;i++) adde(S,p1[i],1,0),adde(p2[i],T,1,0),adde(p1[i],T,1,W);
build(1,n);printf("%lld\n",mcmf().se);
return 0;
}
洛谷 P5331 - [SNOI2019]通信(CDQ 分治优化建图+费用流)的更多相关文章
- P5331 [SNOI2019]通信 [线段树优化建图+最小费用最大流]
这题真让人自闭-我EK费用流已经死了?- (去掉define int long long就过了) 我建的边害死我的 spfa 还是spfa已经死了? 按费用流的套路来 首先呢 把点 \(i\) 拆成两 ...
- 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
[BZOJ4276][ONTAK2015]Bajtman i Okrągły Robin Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2 ...
- 洛谷P3810 陌上花开(CDQ分治)
洛谷P3810 陌上花开 传送门 题解: CDQ分治模板题. 一维排序,二维归并,三维树状数组. 核心思想是分治,即计算左边区间对右边区间的影响. 代码如下: #include <bits/st ...
- 洛谷P4169 天使玩偶 CDQ分治
还是照着CDQ的思路来. 但是有一些改动: 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的.怎么办?旋转!做4次就好了. 统计的不是和,而是——max!理由如下: 设当前点是(x,y ...
- [bzoj] 3263 陌上花开 洛谷 P3810 三维偏序|| CDQ分治 && CDQ分治讲解
原题 定义一个点比另一个点大为当且仅当这个点的三个值分别大于等于另一个点的三个值.每比一个点大就为加一等级,求每个等级的点的数量. 显然的三维偏序问题,CDQ的板子题. CDQ分治: CDQ分治是一种 ...
- HDU3605: Escape-二进制优化建图-最大流
目录 目录 思路: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 目录 题意:传送门 原题目描述在最下面. \(n(n\leq 100000)\)个人\(m(m\leq 10) ...
- 2018.09.27 codeforces1045A. Last chance(线段树优化建图+最大流)
传送门 看完题应该都知道是网络流了吧. 但是第二种武器直接建图会gg. 因此我们用线段树优化建图. 具体操作就是,对于这m个人先建一棵线段树,父亲向儿子连容量为inf的边,最后叶子结点向对应的人连容量 ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP
洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...
- 洛谷P3783 [SDOI2017]天才黑客(前后缀优化建图+虚树+最短路)
题面 传送门 题解 去看\(shadowice\)巨巨写得前后缀优化建图吧 话说我似乎连线段树优化建图的做法都不会 //minamoto #include<bits/stdc++.h> # ...
随机推荐
- Java项目中常用的的五大设计原则
今天我们一起来聊聊关于设计原则相关的知识点. SOLID五大原则是什么 SRP 单一责任原则 单一责任原则,从名字上我们就能比较好的去理解它.这项原则主张一个对象只专注于单个方面的逻辑,强调了职责的专 ...
- 【UE4 C++】Input 输入事件绑定
轴映射与动作映射 编辑器设置input+代码实现具体动作 void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInp ...
- Zabbix 5.0:监控阿里云RDS
Blog:博客园 个人 由于近期压测,需要频繁登录阿里云查看RDS监控,每次登录查看监控步骤较为繁琐,故将监控接入到zabbix. 概述 由于阿里云已做了RDS的监控,我们只需要通过阿里云SDK把这些 ...
- Noip模拟29(瞎眼忌) 2021.8.3
T1 最长不下降子序列 在此记录自己的瞎眼... 考场上像一个傻$der$,自己为了防范上升序列和不下降序列的不同特意的造了一组$hack$数据来卡自己:(第一行是序列长度,第二行是序列) 6 1 5 ...
- Linux C 数据结构 ->单向链表
之前看到一篇单向链表的博文,代码也看着很舒服,于是乎记录下来,留给自己~,循序渐进,慢慢 延伸到真正的内核链表~(敢问路在何方?路在脚下~) 1. 简介 链表是Linux 内核中最简单,最普通的数据结 ...
- Spring Cache 带你飞(一)
Spring 3.1 版本引入基于 annotation 的 cache 技术,提供了一套抽象的缓存实现方案,通过注解方式使用缓存,基于配置的方式灵活使用不同缓存组件.代码具有相当的灵活性和扩展性,本 ...
- hdu 1847 Good Luck in CET-4 Everybody! (简单博弈)
题意: n张牌,双方轮流抓取.每人每次抓取的牌数必须是2的幂次(1,2,4,8...). 最后抓完的人胜. 思路 : 考虑剩3张牌,后手胜. 考虑3的倍数.假设先抓者当轮抓2x 张,2x %3等于1或 ...
- 测试开发【提测平台】分享13-远程搜索和路由$route使用实现新建提测需求
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 本篇继续提测平台开发,按惯例先给出学习的思维导图,以便快速了解学习知识和平台功能实现的重点. 基本知识点学习 远程搜索 显示的数据通过输入 ...
- 前端---梳理 http 知识体系 1
最近看了http相关的知识点,觉得还是有必要整理下,这样对自己的网络知识体系也有帮助. http 是什么 http叫超文本传输协议,可以拆成超文本.传输.协议来理解 协议 http 是一个用在计算机里 ...
- 三、其他主机安装zabbix-agent加入到zabbix
一.yum (rpm)方式 1,下载安装对应的zabbix-agent的rpm包 rpm -Uvh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/ ...