一、题目

点此看题

二、解法

一看就是傻逼补流模型,不会真的有人这个图都建不出来吧

别走啊,我不阴阳怪气了,如果你不知道怎么建这里有图嘛(思路来源是餐巾计划问题):

其中标红的边数量级很大,因为 \(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)\) ,所以没啥问题啦,如果你没写错是不会出现负环的。

因为我懒所以我写的第二种做法,但我坚信主席树是可以做到的:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <queue>
  5. using namespace std;
  6. const int M = 100005;
  7. #define int long long
  8. const int inf = 1e18;
  9. int read()
  10. {
  11. int x=0,f=1;char c;
  12. while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
  13. while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
  14. return x*f;
  15. }
  16. int n,w,tot,cnt,f[M],a[M],b[M],id[M];
  17. int cost,s,t,dis[M],lst[M],pre[M],in[M],flow[M];
  18. struct edge
  19. {
  20. int v,f,c,next;
  21. edge(int V=0,int F=0,int C=0,int N=0) :
  22. v(V) , f(F) , c(C) , next(N) {}
  23. }e[10*M];
  24. void add(int u,int v,int c,int fl)
  25. {
  26. e[++tot]=edge(v,fl,c,f[u]),f[u]=tot;
  27. e[++tot]=edge(u,0,-c,f[v]),f[v]=tot;
  28. }
  29. void cdq(int l,int r)
  30. {
  31. if(l==r) return ;
  32. int mid=(l+r)>>1;
  33. cdq(l,mid);
  34. cdq(mid+1,r);
  35. //现在要考虑[l,mid]连到[mid+1,r]的边
  36. for(int i=l;i<=r;i++)
  37. {
  38. b[i]=a[i];
  39. id[i]=++cnt;//建虚点
  40. }
  41. sort(b+l,b+r+1);
  42. for(int i=l;i<r;i++)
  43. {
  44. add(id[i+1],id[i],b[i+1]-b[i],inf);
  45. add(id[i],id[i+1],b[i+1]-b[i],inf);
  46. }
  47. for(int i=l;i<=r;i++)
  48. {
  49. int t=lower_bound(b+l,b+r+1,a[i])-b;
  50. if(i<=mid) add(i+n,id[t],0,1);
  51. else add(id[t],i,0,1);
  52. }
  53. }
  54. int bfs()
  55. {
  56. queue<int> q;
  57. for(int i=0;i<=cnt;i++) dis[i]=inf;
  58. dis[s]=0;pre[s]=-1;flow[s]=inf;
  59. q.push(s);
  60. while(!q.empty())
  61. {
  62. int u=q.front();q.pop();
  63. in[u]=0;
  64. for(int i=f[u];i;i=e[i].next)
  65. {
  66. int v=e[i].v,c=e[i].c;
  67. if(dis[v]>dis[u]+c && e[i].f>0)
  68. {
  69. dis[v]=dis[u]+c;
  70. pre[v]=u;lst[v]=i;
  71. flow[v]=min(flow[u],e[i].f);
  72. if(!in[v]) in[v]=1,q.push(v);
  73. }
  74. }
  75. }
  76. return dis[t]<inf;
  77. }
  78. int Abs(int x)
  79. {
  80. return x>0?x:-x;
  81. }
  82. signed main()
  83. {
  84. n=read();w=read();
  85. s=0;cnt=t=2*n+1;tot=1;
  86. for(int i=1;i<=n;i++)
  87. {
  88. a[i]=read();
  89. add(s,i,w,1);
  90. add(i,t,0,1);
  91. add(s,i+n,0,1);
  92. }
  93. cdq(1,n);
  94. while(bfs())
  95. {
  96. cost+=dis[t]*flow[t];
  97. int zy=t;
  98. while(zy!=s)
  99. {
  100. e[lst[zy]].f-=flow[t];
  101. e[lst[zy]^1].f+=flow[t];
  102. zy=pre[zy];
  103. }
  104. }
  105. printf("%lld\n",cost);
  106. }

[SNOI2019] 通信的更多相关文章

  1. 【LOJ#3097】[SNOI2019]通信(费用流)

    [LOJ#3097][SNOI2019]通信(费用流) 题面 LOJ 题解 暴力就直接连\(O(n^2)\)条边. 然后分治/主席树优化连边就行了. 抄zsy代码,zsy代码是真的短 #include ...

  2. 【洛谷P5331】 [SNOI2019]通信

    洛谷 题意: \(n\)个哨站排成一列,第\(i\)个哨站的频段为\(a_i\). 现在每个哨站可以选择: 直接连接到中心,代价为\(w\): 连接到前面某个哨站\(j(j<i)\),代价为\( ...

  3. LOJ3097 SNOI2019 通信 题解

    题目链接 费用流,当建边需要依靠位置和权值两个偏序关系时,可以用cdq分治优化建边. 代码: #include<bits/stdc++.h> using namespace std; #d ...

  4. luogu P5331 [SNOI2019]通信

    传送门 有匹配次数限制,求最小代价,这显然是个费用流的模型.每个点暴力和前面的点连匹配边,边数是\(n^2\)的. 然后发现可以转化成一个set,每次加入一个点,然后入点对set里面的出点连边.这个s ...

  5. LOJ#3097 [SNOI2019]通信 最小费用最大流+cdq分治/主席树/分块优化建图

    瞎扯 我们网络流模拟赛(其实是数据结构模拟赛)的T2. 考场上写主席树写自闭了,直接交了\(80pts\)的暴力,考完出来突然发现: woc这个题一个cdq几行就搞定了! 题意简述 有\(n\)个哨站 ...

  6. P5331 [SNOI2019]通信 [线段树优化建图+最小费用最大流]

    这题真让人自闭-我EK费用流已经死了?- (去掉define int long long就过了) 我建的边害死我的 spfa 还是spfa已经死了? 按费用流的套路来 首先呢 把点 \(i\) 拆成两 ...

  7. 题解 洛谷 P5331 【[SNOI2019]通信】

    考虑用费用流解决本题. 每个哨站看作一个点,并将其拆为两个点,建图方式为: \(S \longrightarrow x_i\) 容量为\(1\),费用为\(0\) \(x_i \longrightar ...

  8. 洛谷 P5331 - [SNOI2019]通信(CDQ 分治优化建图+费用流)

    题面传送门 首先熟悉网络流的同学应该能一眼看出此题的建模方法: 将每个点拆成两个点 \(in_i,out_i\),连一条 \(S\to in_i\),容量为 \(1\) 费用为 \(0\) 的边 连一 ...

  9. 【LOJ】#3097. 「SNOI2019」通信

    LOJ#3097. 「SNOI2019」通信 费用流,有点玄妙 显然按照最小路径覆盖那题的建图思路,把一个点拆成两种点,一种是从这个点出去,标成\(x_{i}\),一种是输入到这个点,使得两条路径合成 ...

随机推荐

  1. K8S(13)监控实战-部署prometheus

    k8s监控实战-部署prometheus 目录 k8s监控实战-部署prometheus 1 prometheus前言相关 1.1 Prometheus的特点 1.2 基本原理 1.2.1 原理说明 ...

  2. MySQL 事务特征 & 隔离级别

    数据库事务特征 Atomicity 原子性 事务是一个原子性质的操作单元,事务里面的对数据库的操作要么都执行,要么都不执行, Consistent 一致性 在事务开始之前和完成之后,数据都必须保持一致 ...

  3. 二进制安装kubernetes(一) 环境准备及etcd组件安装及etcd管理软件etcdkeeper安装

    实验环境: 架构图: 主机环境: 操作系统:因docker对内核需要,本次部署操作系统全部采用centos7.6(需要内核3.8以上) VM :2C 2G 50G * 5  PS:因后面实验需要向k8 ...

  4. hdu-1159 1087 1257(dp)

    本文就最长公共子序列,最长连续递增子序列的长度,最大连续递增子序列的值进行对比. hdu-1159: Common Subsequence Time Limit: 2000/1000 MS (Java ...

  5. npm 安装 electron 失败的解决方案

    npm 安装 electron 失败的解决方案 shit GFW npm 安装 electron 失败 解决方案 https://www.npmjs.com/package/nrm $ nrm ls ...

  6. TypeScript tuple 元组

    TypeScript tuple 元组 元组类型允许您用固定数量的元素表示数组,这些元素的类型是已知的,但不必相同. "use strict"; /** * * @author x ...

  7. array auto slice

    array auto slice https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Ar ...

  8. py conda 换源

    安装软件 $ conda install wxpython 如果出现http错误,安装OpenSSL $ conda config --add channels https://mirrors.tun ...

  9. Mac Benchmarks

    Mac Benchmarks https://browser.geekbench.com/mac-benchmarks https://www.geekbench.com/ https://www.f ...

  10. NLog整合Exceptionless

    前言 在实际的.Net Core相关项目开发中,很多人都会把NLog作为日志框架的首选,主要是源于它的强大和它的扩展性.同时很多时候我们需要集中式的采集日志,这时候仅仅使用NLog是不够的,NLog主 ...