LOJ#2134 小园丁与老司机
我的妈呀,这码农神题......
第一问是个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 小园丁与老司机相关推荐
- P2304 [NOI2015] 小园丁与老司机(网络流/上下界网络流)
P2304 [NOI2015] 小园丁与老司机 平面上有n个点,每次可以向左.右.上.左上45度.右上45度移动,然后直线移动到达第一个没有到过的点,如果没有这样的点就不能移动,求解一条最长路,然后求 ...
- BZOJ4200 洛谷2304 UOJ132:[NOI2015]小园丁与老司机——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4200 https://www.luogu.org/problemnew/show/P2304 ht ...
- 提高千倍效率的35个编码小技巧,老司机带你飞!
点击关注公众号,实用技术文章及时了解 来源:henleylee.github.io/posts/2019/a780fcc1.html 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的 ...
- mysql入门到跑路_Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26
1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis mongoab memcache 2. 请简述数据库管理系统的作用 数据存 ...
- oracle从删库到跑路,Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26
1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis mongoab memcache 2. 请简述数据库管理系统的作用 数据存 ...
- 年薪30W的软件测试“老司机”工作经验
这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...
- 【新梦想学员干货】必看!年薪30W的软件测试“老司机”工作经验。
这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...
- 名悦集团:开车从不追尾,老司机分享驾驶避免事故小知识
听交通广播,我们几乎每天都能听到高速路上,高架桥上,上班路上发生追尾事故,有时候是个平常的上下班高峰期.很多人会纳闷,车开的好好的,怎么就会发生追尾事故呢.开车在路上,难免会有磕磕碰碰.道路千万条,安 ...
- 老司机都在用的浏览器,体积小功能齐全,直呼内行
现在市面上的浏览器简直是多不胜数,虽然数量多,但是好用的并不多.尤其是某些大厂的浏览器,无用的功能越来越多,越来越臃肿,体积也越来越大,使用体验还不好,有时候甚至不如一些小众浏览器.今天给大家安利2款 ...
- 视频教程-老司机讲前端之微信小程序开发成语消消乐游戏视频课程-微信开发
老司机讲前端之微信小程序开发成语消消乐游戏视频课程 中国实战派HTML5培训第一人,微软技术讲师,曾任百合网技术总监,博看文思HTML5总监.陶国荣长期致力于HTML5.JavaScript.CSS3 ...
最新文章
- office365加速解决方案
- git 修改分支名字_开发中必须要掌握的 Git 技巧
- 深度学习方法笔记之(一):SVM的基本模型
- 2017-10-9(Volley使用范例源码分析)
- 第二批鸿蒙手机排行,鸿蒙系统第二批升级机型有哪些 鸿蒙系统第二批升级机型名单一览...
- 010 、JVM实战总结: 动手实验:亲自感受一下线上系统部署时如何设置JVM内存大小
- 2021国赛数学建模赛题与分析
- 10大城市硬科技指数发布,“硬科技+在大西安”高峰论坛圆满落幕
- 绝对值线性化的两种方式
- mysql误删除数据恢复处理
- 自定义插入页面标签以及实现类似通讯录的首字母搜索
- 元旦节快乐,新的一年新的福利,给大家准备了高清无码的白虎图
- visio的图在word中空白处太大的问题
- led灯条维修_LED灯坏了怎么维修?学会自己动手,简单的LED故障自己也能维修
- QT_地图导航 源码下载
- bzoj3786星系探索(splay维护dfs序)
- 关于峰均比的一些记录
- Axure 真正的解决跳转事件无效
- speedtest测速
- 经管丨《蓝海战略》:全球畅销书,超越竞争思维,开创全新市场
热门文章
- 详细解读php的命名空间(一)
- stm32使用cubemx生成HAL库工程驱动mlx90614
- python turtle渐变色_Python : turtle色彩控制实例详解
- 计算机无法通过网络连接打印机共享,共享打印机无法连接,详细教您共享打印机无法连接怎么办...
- 公路通用复化辛普森公式匝道点位坐标计算4800源程序
- 计算机处理器性能排名,2018电脑英特尔处理器排名(cpu性能天梯图)
- LightBox -灯箱效果插件(非常漂亮) Jquery灯箱效果
- 计算机网络共享文件共享,终于发现如何取消计算机网络共享文件
- uni-app改变radio的默认样式 去掉小对号
- qq邮箱对方服务器退回,为什么我用QQ邮箱发邮件被退回来了?他说地 – 手机爱问...