我的妈呀,这码农神题......

第一问是个DP,要记录方案。先把纵向的转移建图。发现可以按照y坐标来划分阶段,每一层vector存一下,用前后缀最大值来转移。

第二问考虑所有可能成为最优方案的边。从终点倒推可以保证每条边都能到起点,而从起点出发就不一定能保证。这些边拿去网络流建图,然后最小流。

注意第二问找边的时候,每一层的点其实可以视作两个,经过同层转移的和未经过的。这两者不可混为一谈。

最小流先跑S -> T然后t -> s退流的话,要用当前弧优化,否则会被最后一个数据卡成n²。

  1 #include <bits/stdc++.h>
  2
  3 const int N = 50010, INF = 0x7f7f7f7f;
  4
  5 struct Node {
  6     int x, y, id;
  7     inline bool operator <(const Node &w) const {
  8         if(y != w.y) return y < w.y;
  9         return x < w.x;
 10     }
 11 }node[N];
 12
 13 inline void read(int &x) {
 14     x = 0;
 15     char c = getchar();
 16     bool f = 0;
 17     while(c < '0' || c > '9') {
 18         if(c == '-') f = 1;
 19         c = getchar();
 20     }
 21     while(c >= '0' && c <= '9') {
 22         x = x * 10 + c - 48;
 23         c = getchar();
 24     }
 25     if(f) x = (~x) + 1;
 26     return;
 27 }
 28
 29 struct Edge {
 30     int nex, v;
 31 }edge[N << 2]; int tp;
 32
 33 int n, X[N << 2], xx, bin[N << 2], e[N], fr1[N], fr2[N], fr_l[N], fr_r[N], large_l[N], large_r[N], f[N], ff[N];
 34 bool visit[N], visit2[N];
 35 std::vector<int> v[N << 2];
 36
 37 inline void add(int x, int y) {
 38     tp++;
 39     edge[tp].v = y;
 40     edge[tp].nex = e[x];
 41     e[x] = tp;
 42     return;
 43 }
 44
 45 void out(int x, int flag) {
 46     if(!node[x].id) return;
 47     if(flag == 1) {
 48         out(fr1[x], 2);
 49     }
 50     else {
 51         out(fr2[x], 1);
 52         int y = fr2[x], u = node[y].y;
 53         if(y == x) {
 54             printf("%d ", node[x].id);
 55         }
 56         else if(node[y].x > node[x].x) {
 57             for(int i = 0; i < (int)(v[u].size()); i++) {
 58                 if(node[v[u][i]].x >= node[y].x) {
 59                     printf("%d ", node[v[u][i]].id);
 60                 }
 61             }
 62             for(int i = v[u].size() - 1; i >= 0; i--) {
 63                 int temp = node[v[u][i]].x;
 64                 if(temp < node[y].x && temp >= node[x].x) {
 65                     printf("%d ", node[v[u][i]].id);
 66                 }
 67             }
 68         }
 69         else {
 70             for(int i = v[u].size() - 1; i >= 0; i--) {
 71                 if(node[v[u][i]].x <= node[y].x) {
 72                     printf("%d ", node[v[u][i]].id);
 73                 }
 74             }
 75             for(int i = 0; i < (int)(v[u].size()); i++) {
 76                 int temp = node[v[u][i]].x;
 77                 if(temp > node[y].x && temp <= node[x].x) {
 78                     printf("%d ", node[v[u][i]].id);
 79                 }
 80             }
 81         }
 82     }
 83     return;
 84 }
 85
 86 namespace fl {
 87     struct Edge {
 88         int nex, v, c;
 89         Edge(int Nex = 0, int V = 0, int C = 0) {
 90             nex = Nex;
 91             v = V;
 92             c = C;
 93         }
 94     }edge[1000010]; int tp = 1;
 95     int e[N], vis[N], in[N], d[N], vis2[N], cur[N];
 96     std::queue<int> Q;
 97     inline void add(int x, int y, int z) {
 98         edge[++tp] = Edge(e[x], y, z);
 99         e[x] = tp;
100         edge[++tp] = Edge(e[y], x, 0);
101         e[y] = tp;
102         return;
103     }
104     inline void Add(int x, int y) {
105         /// x -> y [1, INF]
106         vis2[x] = vis2[y] = 1;
107         add(x, y, N);
108         in[y]++;
109         in[x]--;
110         return;
111     }
112     inline bool BFS(int s, int t) {
113         static int Time = 0; Time++;
114         vis[s] = Time;
115         d[s] = 0;
116         Q.push(s);
117         while(!Q.empty()) {
118             int x = Q.front();
119             Q.pop();
120             for(int i = e[x]; i; i = edge[i].nex) {
121                 int y = edge[i].v;
122                 if(vis[y] != Time && edge[i].c) {
123                     vis[y] = Time;
124                     d[y] = d[x] + 1;
125                     Q.push(y);
126                 }
127             }
128         }
129         return vis[t] == Time;
130     }
131     int DFS(int x, int t, int maxF) {
132         if(x == t) return maxF;
133         int ans = 0;
134         for(int i = cur[x] ? cur[x] : e[x]; i; i = edge[i].nex) {
135             int y = edge[i].v;
136             if(!edge[i].c || d[y] != d[x] + 1) {
137                 continue;
138             }
139             int temp = DFS(y, t, std::min(maxF - ans, edge[i].c));
140             if(!temp) d[y] = INF;
141             ans += temp;
142             edge[i].c -= temp;
143             edge[i ^ 1].c += temp;
144             if(ans == maxF) break;
145             cur[x] = i;
146         }
147         return ans;
148     }
149     inline int dinic(int s, int t) {
150         int ans = 0;
151         while(BFS(s, t)) {
152             memset(cur, 0, sizeof(cur));
153             ans += DFS(s, t, INF);
154         }
155         return ans;
156     }
157     inline void solve() {
158         int s = N - 5, t = N - 2, S = N - 3, T = N - 4;
159         for(int i = 1; i <= n; i++) {
160             if(!vis2[i]) continue;
161             add(s, i, N);
162             add(i, t, N);
163         }
164         int now = tp;
165         add(t, s, INF);
166         for(int i = 1; i <= n; i++) {
167             if(in[i] > 0) {
168                 add(S, i, in[i]);
169             }
170             else if(in[i] < 0) {
171                 add(i, T, -in[i]);
172             }
173         }
174         int ans;
175         dinic(S, T);
176         ans = edge[now + 2].c;
177         for(int i = now + 1; i <= tp; i++) edge[i].c = 0;
178         ans -= dinic(t, s);
179         printf("%d\n", ans);
180         return;
181     }
182 }
183
184 int main() {
185     read(n);
186     for(int i = 1; i <= n; i++) {
187         read(node[i].x); read(node[i].y);
188         node[i].id = i;
189         X[++xx] = node[i].x;
190         X[++xx] = node[i].y;
191         X[++xx] = node[i].x + node[i].y;
192         X[++xx] = node[i].x - node[i].y;
193     }
194     ++n; ++xx; /// the Node O
195     std::sort(node + 1, node + n + 1);
196     std::sort(X + 1, X + xx + 1);
197     xx = std::unique(X + 1, X + xx + 1) - X - 1;
198     for(int i = 1; i <= n; i++) {
199         int temp = std::lower_bound(X + 1, X + xx + 1, node[i].x + node[i].y) - X;
200         if(bin[temp]) {
201             add(bin[temp], i);
202         }
203         bin[temp] = i;
204     }
205     memset(bin + 1, 0, xx * sizeof(int));
206     for(int i = 1; i <= n; i++) {
207         int temp = std::lower_bound(X + 1, X + xx + 1, node[i].x - node[i].y) - X;
208         if(bin[temp]) {
209             add(bin[temp], i);
210         }
211         bin[temp] = i;
212     }
213     memset(bin + 1, 0, xx * sizeof(int));
214     for(int i = 1; i <= n; i++) {
215         node[i].x = std::lower_bound(X + 1, X + xx + 1, node[i].x) - X;
216         node[i].y = std::lower_bound(X + 1, X + xx + 1, node[i].y) - X;
217     }
218     for(int i = 1; i <= n; i++) {
219         if(bin[node[i].x]) {
220             add(bin[node[i].x], i);
221         }
222         bin[node[i].x] = i;
223         v[node[i].y].push_back(i);
224     }
225     /// Build Graph 1 Over
226     memset(f, ~0x3f, sizeof(f));
227     f[1] = 0;
228     for(int u = 1; u <= xx; u++) {
229         if(!v[u].size()) continue;
230         int len = v[u].size();
231         for(int i = 0; i < len; i++) {
232             int x = v[u][i];
233             ff[x] = f[x];
234             fr2[x] = x;
235         }
236         /// trans in row
237         for(int i = 0; i < len; i++) {
238             int x = v[u][i];
239             if(i && f[x] < large_l[i - 1]) {
240                 large_l[i] = large_l[i - 1];
241                 fr_l[i] = fr_l[i - 1];
242             }
243             else {
244                 large_l[i] = f[x];
245                 fr_l[i] = x;
246             }
247         }
248         for(int i = len - 1; i >= 0; i--) {
249             int x = v[u][i];
250             if(i < len - 1 && f[x] < large_r[i + 1]) {
251                 large_r[i] = large_r[i + 1];
252                 fr_r[i] = fr_r[i + 1];
253             }
254             else {
255                 large_r[i] = f[x];
256                 fr_r[i] = x;
257             }
258         }
259         for(int i = 0; i < len; i++) {
260             int x = v[u][i];
261             if(i < len - 1 && f[x] < large_r[i + 1] + len - i - 1) {
262                 f[x] = large_r[i + 1] + len - i - 1;
263                 fr2[x] = fr_r[i + 1];
264             }
265             if(i && f[x] < large_l[i - 1] + i) {
266                 f[x] = large_l[i - 1] + i;
267                 fr2[x] = fr_l[i - 1];
268             }
269         }
270         /// trans in cross / other
271         for(int i = 0; i < len; i++) {
272             int x = v[u][i];
273             for(int i = e[x]; i; i = edge[i].nex) {
274                 int y = edge[i].v;
275                 if(f[y] < f[x] + 1) {
276                     f[y] = f[x] + 1;
277                     fr1[y] = x;
278                 }
279             }
280         }
281     }
282     /// DP OVER
283     int large_val = -INF, ans_pos = 0;
284     for(int i = 1; i <= n; i++) {
285         if(large_val < f[i]) {
286             large_val = f[i];
287             ans_pos = i;
288         }
289     }
290     printf("%d\n", large_val);
291     out(ans_pos, 2);
292     /// Out OVER
293     for(int i = 1; i <= n; i++) {
294         if(f[i] == large_val) visit2[i] = 1;
295         if(ff[i] == large_val) visit[i] = 1;
296     }
297     for(int u = xx; u >= 1; u--) {
298         if(!v[u].size()) continue;
299         int len = v[u].size();
300         /// build Flow Graph (this -> up)
301         for(int i = 0; i < len; i++) {
302             int x = v[u][i];
303             for(int i = e[x]; i; i = edge[i].nex) {
304                 int y = edge[i].v;
305                 if(visit[y] && ff[y] == f[x] + 1) {
306                     visit2[x] = 1;
307                     fl::Add(x, y);
308                 }
309             }
310             if(visit2[x] && f[x] == ff[x]) {
311                 visit[x] = 1;
312             }
313         }
314         /// Find Edge in row (update)
315         for(int j = 0; j < len; j++) {
316             int y = v[u][j];
317             if(!visit2[y]) continue;
318             for(int i = 0; i < len; i++) {
319                 int x = v[u][i];
320                 if(visit[x]) continue;
321                 /// x -> y
322                 if(node[x].x < node[y].x && f[y] == ff[x] + j) {
323                     visit[x] = 1;
324                 }
325                 else if(node[y].x < node[x].x && f[y] == ff[x] + len - j - 1) {
326                     visit[x] = 1;
327                 }
328             }
329         }
330     }
331     puts("");
332     /// Build Flow Over
333     fl::solve();
334     return 0;
335 }

AC代码

10k还行

转载于:https://www.cnblogs.com/huyufeifei/p/10580049.html

LOJ#2134 小园丁与老司机相关推荐

  1. P2304 [NOI2015] 小园丁与老司机(网络流/上下界网络流)

    P2304 [NOI2015] 小园丁与老司机 平面上有n个点,每次可以向左.右.上.左上45度.右上45度移动,然后直线移动到达第一个没有到过的点,如果没有这样的点就不能移动,求解一条最长路,然后求 ...

  2. BZOJ4200 洛谷2304 UOJ132:[NOI2015]小园丁与老司机——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4200 https://www.luogu.org/problemnew/show/P2304 ht ...

  3. 提高千倍效率的35个编码小技巧,老司机带你飞!

    点击关注公众号,实用技术文章及时了解 来源:henleylee.github.io/posts/2019/a780fcc1.html 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的 ...

  4. mysql入门到跑路_Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26

    1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis  mongoab  memcache 2. 请简述数据库管理系统的作用 数据存 ...

  5. oracle从删库到跑路,Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26

    1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis  mongoab  memcache 2. 请简述数据库管理系统的作用 数据存 ...

  6. 年薪30W的软件测试“老司机”工作经验

    这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...

  7. 【新梦想学员干货】必看!年薪30W的软件测试“老司机”工作经验。

    这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...

  8. 名悦集团:开车从不追尾,老司机分享驾驶避免事故小知识

    听交通广播,我们几乎每天都能听到高速路上,高架桥上,上班路上发生追尾事故,有时候是个平常的上下班高峰期.很多人会纳闷,车开的好好的,怎么就会发生追尾事故呢.开车在路上,难免会有磕磕碰碰.道路千万条,安 ...

  9. 老司机都在用的浏览器,体积小功能齐全,直呼内行

    现在市面上的浏览器简直是多不胜数,虽然数量多,但是好用的并不多.尤其是某些大厂的浏览器,无用的功能越来越多,越来越臃肿,体积也越来越大,使用体验还不好,有时候甚至不如一些小众浏览器.今天给大家安利2款 ...

  10. 视频教程-老司机讲前端之微信小程序开发成语消消乐游戏视频课程-微信开发

    老司机讲前端之微信小程序开发成语消消乐游戏视频课程 中国实战派HTML5培训第一人,微软技术讲师,曾任百合网技术总监,博看文思HTML5总监.陶国荣长期致力于HTML5.JavaScript.CSS3 ...

最新文章

  1. 局域网网速带宽测试软件,网管的经验 教你如何测试局域网的网速
  2. (计算机组成原理)第五章中央处理器-第四节2:微程序控制器基本原理
  3. 百度编辑器 Ueditor 如何增加模板 ?
  4. linux-vim编辑器简览
  5. [GPL]GREP - basic - practice -advanced
  6. ContentPresenter
  7. react 项目实战(二)创建 用户添加 页面 及 fetch请求 json-server db.json -w -p 8000...
  8. 观察者模式 - dom事件 / 自定义事件 / Promise 我的理解
  9. [tensorflow]win 环境 安装anacoda 4.8.2 和tensorflow 2.1.0
  10. 【React Native 安卓开发】----(Flexbox布局)【第二篇】
  11. html中有序列表的css样式,CSS 列表样式(ul)
  12. debian9 使用cups远程管理打印服务
  13. 基于51单片机的7键8键电子琴proteus仿真数码管显示程序原理设计
  14. php实现五维雷达图,【数据可视化·图表篇】雷达图
  15. matlab质心定位算法,一种改进的质心定位算法
  16. html5拖拽实现拼图,HTML5技术之图像处理:一个滑动的拼图游戏
  17. IOTA--最便捷的网络流量分析工具
  18. 信用风险建模 in Python 系列 7 - ASRF 模型
  19. linux系统中的分区与挂载,以及使用LVM逻辑卷管理器管理物理卷,卷组,逻辑卷知识点总结
  20. 为iPart表添加“重量”列

热门文章

  1. 微信公众号开发:实人认证,活体人脸识别解决方案
  2. Python3开发 语法(四)
  3. 2018 PKU_WC 长沙游 《我到长沙来看雪》
  4. 2.7 SLD参考标准与GeoServer扩展
  5. SAP PI SLD RZ70 系统架构目录数据提供者 HTTP(S) 配置
  6. 从少年变成老男孩-----韩寒与郭敬明的十年
  7. [好歌推荐4]侯德建 - 归去来兮
  8. P4199 万径人踪灭 [Manacher + FFT]
  9. TIPTOP、T100系统程序的内置函数使用详解
  10. 新浪云应用 mysql_云应用开发之新浪SAE读写云端数据库MySQL