[SNOI2019] 通信
一、题目
二、解法
一看就是傻逼补流模型,不会真的有人这个图都建不出来吧
别走啊,我不阴阳怪气了,如果你不知道怎么建这里有图嘛(思路来源是餐巾计划问题
):
其中标红的边数量级很大,因为 \(i\) 点拆出来的点 \(i'\) 要连后面的每一个点 \(j\) ,边的数量达到了 \(n^2\) ,如果直接无脑暴力刚那肯定会吃 \(T\) 的,我测试过暴力跑的话只能得 \(80\) 分。
现在肯定要优化建图了,貌似可以可持久化权值线段树优化建图,因为 \(i<j\) 的每个点都要连所以建出后缀的权值线段树,然后分两部分连边。不过这里有一种小清新的做法,可以欣赏一下:
考虑类 \(\tt cdq\) 分治,每次考虑 \([l,mid]\) 连向 \([mid+1,r]\) 的边,可以把 \([l,r]\) 所有的权值取出来,每个权值都建一个虚点,排序之后相邻地连起来,容量为 \(inf\) 费用为权值之差。\([l,mid]\) 的点连向对应权值的虚点,对应权值的虚点连向 \([mid+1,r]\) 中的点,如果你觉得有点抽象这里还是有我精心(随便)绘制的图:
现在边数和点数都变成了 \(O(n\log n)\) ,所以没啥问题啦,如果你没写错是不会出现负环的。
因为我懒所以我写的第二种做法,但我坚信主席树是可以做到的:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int M = 100005;
#define int long long
const int inf = 1e18;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,w,tot,cnt,f[M],a[M],b[M],id[M];
int cost,s,t,dis[M],lst[M],pre[M],in[M],flow[M];
struct edge
{
int v,f,c,next;
edge(int V=0,int F=0,int C=0,int N=0) :
v(V) , f(F) , c(C) , next(N) {}
}e[10*M];
void add(int u,int v,int c,int fl)
{
e[++tot]=edge(v,fl,c,f[u]),f[u]=tot;
e[++tot]=edge(u,0,-c,f[v]),f[v]=tot;
}
void cdq(int l,int r)
{
if(l==r) return ;
int mid=(l+r)>>1;
cdq(l,mid);
cdq(mid+1,r);
//现在要考虑[l,mid]连到[mid+1,r]的边
for(int i=l;i<=r;i++)
{
b[i]=a[i];
id[i]=++cnt;//建虚点
}
sort(b+l,b+r+1);
for(int i=l;i<r;i++)
{
add(id[i+1],id[i],b[i+1]-b[i],inf);
add(id[i],id[i+1],b[i+1]-b[i],inf);
}
for(int i=l;i<=r;i++)
{
int t=lower_bound(b+l,b+r+1,a[i])-b;
if(i<=mid) add(i+n,id[t],0,1);
else add(id[t],i,0,1);
}
}
int bfs()
{
queue<int> q;
for(int i=0;i<=cnt;i++) dis[i]=inf;
dis[s]=0;pre[s]=-1;flow[s]=inf;
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
in[u]=0;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v,c=e[i].c;
if(dis[v]>dis[u]+c && e[i].f>0)
{
dis[v]=dis[u]+c;
pre[v]=u;lst[v]=i;
flow[v]=min(flow[u],e[i].f);
if(!in[v]) in[v]=1,q.push(v);
}
}
}
return dis[t]<inf;
}
int Abs(int x)
{
return x>0?x:-x;
}
signed main()
{
n=read();w=read();
s=0;cnt=t=2*n+1;tot=1;
for(int i=1;i<=n;i++)
{
a[i]=read();
add(s,i,w,1);
add(i,t,0,1);
add(s,i+n,0,1);
}
cdq(1,n);
while(bfs())
{
cost+=dis[t]*flow[t];
int zy=t;
while(zy!=s)
{
e[lst[zy]].f-=flow[t];
e[lst[zy]^1].f+=flow[t];
zy=pre[zy];
}
}
printf("%lld\n",cost);
}
[SNOI2019] 通信的更多相关文章
- 【LOJ#3097】[SNOI2019]通信(费用流)
[LOJ#3097][SNOI2019]通信(费用流) 题面 LOJ 题解 暴力就直接连\(O(n^2)\)条边. 然后分治/主席树优化连边就行了. 抄zsy代码,zsy代码是真的短 #include ...
- 【洛谷P5331】 [SNOI2019]通信
洛谷 题意: \(n\)个哨站排成一列,第\(i\)个哨站的频段为\(a_i\). 现在每个哨站可以选择: 直接连接到中心,代价为\(w\): 连接到前面某个哨站\(j(j<i)\),代价为\( ...
- LOJ3097 SNOI2019 通信 题解
题目链接 费用流,当建边需要依靠位置和权值两个偏序关系时,可以用cdq分治优化建边. 代码: #include<bits/stdc++.h> using namespace std; #d ...
- luogu P5331 [SNOI2019]通信
传送门 有匹配次数限制,求最小代价,这显然是个费用流的模型.每个点暴力和前面的点连匹配边,边数是\(n^2\)的. 然后发现可以转化成一个set,每次加入一个点,然后入点对set里面的出点连边.这个s ...
- LOJ#3097 [SNOI2019]通信 最小费用最大流+cdq分治/主席树/分块优化建图
瞎扯 我们网络流模拟赛(其实是数据结构模拟赛)的T2. 考场上写主席树写自闭了,直接交了\(80pts\)的暴力,考完出来突然发现: woc这个题一个cdq几行就搞定了! 题意简述 有\(n\)个哨站 ...
- P5331 [SNOI2019]通信 [线段树优化建图+最小费用最大流]
这题真让人自闭-我EK费用流已经死了?- (去掉define int long long就过了) 我建的边害死我的 spfa 还是spfa已经死了? 按费用流的套路来 首先呢 把点 \(i\) 拆成两 ...
- 题解 洛谷 P5331 【[SNOI2019]通信】
考虑用费用流解决本题. 每个哨站看作一个点,并将其拆为两个点,建图方式为: \(S \longrightarrow x_i\) 容量为\(1\),费用为\(0\) \(x_i \longrightar ...
- 洛谷 P5331 - [SNOI2019]通信(CDQ 分治优化建图+费用流)
题面传送门 首先熟悉网络流的同学应该能一眼看出此题的建模方法: 将每个点拆成两个点 \(in_i,out_i\),连一条 \(S\to in_i\),容量为 \(1\) 费用为 \(0\) 的边 连一 ...
- 【LOJ】#3097. 「SNOI2019」通信
LOJ#3097. 「SNOI2019」通信 费用流,有点玄妙 显然按照最小路径覆盖那题的建图思路,把一个点拆成两种点,一种是从这个点出去,标成\(x_{i}\),一种是输入到这个点,使得两条路径合成 ...
随机推荐
- GoAccess 监控工具
GoAccess 基本概述 简易的统计访问量的软件,官方安装教程 GoAccess 安装 # 下载包 [root@web01 ~]# wget http://tar.goaccess.io/goacc ...
- Xtrabackup 物理备份
目录 Xtrabackup 安装 Xtrabackup 备份介绍 Xtrabackup全量备份 准备备份目录 全量备份 查看全量备份内容 Xtrabackup 全量备份恢复数据 删除所有数据库 停止数 ...
- 信号量解决理发师问题(barber)
问题描述及思路 代码 一些细节见注释 这里ret应该用int..忘了改了. 运行结果 因为座位数和到来最大间隔的原因,没有出现全部椅子被占用的情况
- codefoeces 864B
B. Polycarp and Letters time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- Leetcode(35)-搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 你可以假设数组中无重复元素. 这个题目很简单,因为它是给定的排序数组而且没有重 ...
- mark::开源绘图工具graphviz
http://blog.csdn.net/iamljj/article/details/5862930 http://codeforces.com/contest/601/problem/D
- Gym 101170I Iron and Coal(BFS + 思维)题解
题意:有一个有向图,有些点是煤,有些点是铁,但不会同时有铁和煤.现在我要从1出发,占领可以到达的点.问最少占领几个点能同时拥有一个煤和一个铁(1不用占领). 思路:思路很秀啊.我们从1往外bfs,得到 ...
- 使用MCSManager搭建Minecraft服务器
目录 一.准备工作 1.MCSManager Windows环境下安装 Linux安装 2.Minecraft服务端 3.Java 二.配置 1.登录面板 2.上传服务端 3.服务端的配置 三.开启服 ...
- JPG学习笔记3(附完整代码)
#topics h2 { background: rgba(43, 102, 149, 1); border-radius: 6px; box-shadow: 0 0 1px rgba(95, 90, ...
- 买车交税 All In One
中国买车交税 All In One 消费税 增值税 车辆购置税 车船税 关税 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问! 原 ...