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

第一问是个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. office365加速解决方案
  2. git 修改分支名字_开发中必须要掌握的 Git 技巧
  3. 深度学习方法笔记之(一):SVM的基本模型
  4. 2017-10-9(Volley使用范例源码分析)
  5. 第二批鸿蒙手机排行,鸿蒙系统第二批升级机型有哪些 鸿蒙系统第二批升级机型名单一览...
  6. 010 、JVM实战总结: 动手实验:亲自感受一下线上系统部署时如何设置JVM内存大小
  7. 2021国赛数学建模赛题与分析
  8. 10大城市硬科技指数发布,“硬科技+在大西安”高峰论坛圆满落幕
  9. 绝对值线性化的两种方式
  10. mysql误删除数据恢复处理
  11. 自定义插入页面标签以及实现类似通讯录的首字母搜索
  12. 元旦节快乐,新的一年新的福利,给大家准备了高清无码的白虎图
  13. visio的图在word中空白处太大的问题
  14. led灯条维修_LED灯坏了怎么维修?学会自己动手,简单的LED故障自己也能维修
  15. QT_地图导航 源码下载
  16. bzoj3786星系探索(splay维护dfs序)
  17. 关于峰均比的一些记录
  18. Axure 真正的解决跳转事件无效
  19. speedtest测速
  20. 经管丨《蓝海战略》:全球畅销书,超越竞争思维,开创全新市场

热门文章

  1. 详细解读php的命名空间(一)
  2. stm32使用cubemx生成HAL库工程驱动mlx90614
  3. python turtle渐变色_Python : turtle色彩控制实例详解
  4. 计算机无法通过网络连接打印机共享,共享打印机无法连接,详细教您共享打印机无法连接怎么办...
  5. 公路通用复化辛普森公式匝道点位坐标计算4800源程序
  6. 计算机处理器性能排名,2018电脑英特尔处理器排名(cpu性能天梯图)
  7. LightBox -灯箱效果插件(非常漂亮) Jquery灯箱效果
  8. 计算机网络共享文件共享,终于发现如何取消计算机网络共享文件
  9. uni-app改变radio的默认样式 去掉小对号
  10. qq邮箱对方服务器退回,为什么我用QQ邮箱发邮件被退回来了?他说地 – 手机爱问...