4849: [Neerc2016]Mole Tunnels
来源:互联网 发布:紫金桥软件 编辑:程序博客网 时间:2024/05/17 08:16
4849: [Neerc2016]Mole Tunnels
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 34 Solved: 15
[Submit][Status][Discuss]
Description
鼹鼠们在底下开凿了n个洞,由n-1条隧道连接,对于任意的i>1,第i个洞都会和第i/2(取下整)个洞间有一条隧
道,第i个洞内还有ci个食物能供最多ci只鼹鼠吃。一共有m只鼹鼠,第i只鼹鼠住在第pi个洞内,一天早晨,前k只
鼹鼠醒来了,而后n-k只鼹鼠均在睡觉,前k只鼹鼠就开始觅食,最终他们都会到达某一个洞,使得所有洞的ci均大
于等于该洞内醒着的鼹鼠个数,而且要求鼹鼠行动路径总长度最小。现对于所有的1<=k<=m,输出最小的鼹鼠行动
路径的总长度,保证一定存在某种合法方案。
Input
第一行两个数n,m(1<=n,m<=100000),表示有n个洞,m只鼹鼠。
第二行n个整数ci表示第i个洞的食物数。
第三行m个整数pi表示第i只鼹鼠所在洞pi。
Output
输出一行m个整数,第i个整数表示当k=i时最小的鼹鼠行动路径总长度。
Sample Input
5 4
0 0 4 1 1
2 4 5 2
Sample Output
1 1 2 4
HINT
Source
考虑贪心的策略
k 的答案肯定可以在k−1 的基础上,修改一些路径得到
将原图对应到一棵二叉树
对于每条隧道,记录当前方案中,
有多少只鼹鼠从下往上或是从上往下通过
显然这两种情况只能存在其中一种,否则可以相互抵消让答案更优
因为题目中边的限制,这棵二叉树的深度为log2n
暴力枚举第k 只鼹鼠可能的路径
先枚举它往上走的步数,然后往下找到目标点
对于每条隧道,如果这只鼹鼠要从下往上通过,
而之前已经有x(x>0) 只鼹鼠从上往下通过
那么我们通过交换这只鼹鼠和任意一只鼹鼠的后续路径
这条边通过的鼹鼠数量就减少了
于是这样的边权值可以标为−1
每次找出路径都可以转换为二叉树上的区间修改
dfs序+线段数大力维护一下,每次贪心就行了
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<vector>#include<queue>#include<set>#include<map>#include<stack>#include<bitset>#include<ext/pb_ds/priority_queue.hpp>#define min(a,b) ((a) < (b) ? (a) : (b))using namespace std;const int T = 4;const int INF = ~0U>>1;const int maxn = 1E5 + 10;int n,m,dfs_clock,now,len,Ans,dfn[maxn],End[maxn],c[maxn],val[maxn*T] ,Name[maxn],L[maxn],A[maxn],Num[maxn*T],Min[maxn*T],Mark[maxn*T];inline void Dfs(int x){ dfn[x] = ++dfs_clock; Name[dfs_clock] = x; if ((x<<1) <= n) L[x<<1] = L[x] + 1,Dfs(x<<1); if ((x<<1|1) <= n) L[x<<1|1] = L[x] + 1,Dfs(x<<1|1); End[x] = dfs_clock;}inline void maintain(int o){ int lc = (o << 1),rc = (o << 1 | 1); if (Min[lc] < Min[rc]) Min[o] = Min[lc],Num[o] = Num[lc]; else Min[o] = Min[rc],Num[o] = Num[rc];}inline void pushdown(int o,int l,int r){ if (!Mark[o]) return; if (Min[o] != INF) Min[o] += Mark[o]; if (l == r) {val[o] += Mark[o]; Mark[o] = 0; return;} Mark[o<<1] += Mark[o]; Mark[o<<1|1] += Mark[o]; Mark[o] = 0;}inline void Build(int o,int l,int r){ if (l == r) { if (!c[Name[l]]) Min[o] = INF; else Min[o] = L[Name[l]],Num[o] = Name[l]; val[o] = L[Name[l]]; return; } int mid = l + r >> 1; Build(o<<1,l,mid); Build(o<<1|1,mid+1,r); maintain(o);}inline void Search(int o,int l,int r,int ql,int qr){ pushdown(o,l,r); if (Min[o] >= len) return; if (ql <= l && r <= qr) { if (Min[o] < len) len = Min[o],now = Num[o]; return; } int mid = l + r >> 1; if (ql <= mid) Search(o<<1,l,mid,ql,qr); if (qr > mid) Search(o<<1|1,mid+1,r,ql,qr);}inline int Query(int o,int l,int r,int pos){ pushdown(o,l,r); if (l == r) return val[o]; int mid = l + r >> 1; return pos <= mid ? Query(o<<1,l,mid,pos) : Query(o<<1|1,mid+1,r,pos);}inline void Delete(int o,int l,int r,int pos){ pushdown(o,l,r); if (l == r) { Min[o] = INF; Num[o] = 0; return; } int mid = l + r >> 1; if (pos <= mid) Delete(o<<1,l,mid,pos); else pushdown(o<<1,l,mid); if (pos > mid) Delete(o<<1|1,mid+1,r,pos); else pushdown(o<<1|1,mid+1,r); maintain(o);}inline void Modify(int o,int l,int r,int ql,int qr,int k){ if (ql <= l && r <= qr) { Mark[o] += k; pushdown(o,l,r); return; } int mid = l + r >> 1; pushdown(o,l,r); if (ql <= mid) Modify(o<<1,l,mid,ql,qr,k); else pushdown(o<<1,l,mid); if (qr > mid) Modify(o<<1|1,mid+1,r,ql,qr,k); else pushdown(o<<1|1,mid+1,r); maintain(o);}inline void Walk(int x,int y){ --c[y]; if (!c[y]) Delete(1,1,n,dfn[y]); while (L[x] > L[y]) { if (!A[x]) Modify(1,1,n,dfn[x],End[x],-2); ++A[x]; x >>= 1; } while (L[y] > L[x]) { if (A[y] == 1) Modify(1,1,n,dfn[y],End[y],2); --A[y]; y >>= 1; } while (x != y) { if (!A[x]) Modify(1,1,n,dfn[x],End[x],-2); if (A[y] == 1) Modify(1,1,n,dfn[y],End[y],2); ++A[x]; x >>= 1; --A[y]; y >>= 1; }}inline int getint(){ char ch = getchar(); int ret = 0; while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') ret = ret * 10 + ch - '0',ch = getchar(); return ret;}int main(){ #ifdef DMC freopen("DMC.txt","r",stdin); freopen("test.txt","w",stdout); #endif n = getint(); m = getint(); for (int i = 1; i <= n; i++) c[i] = getint(); Dfs(1); Build(1,1,n); for (int i = 1; i <= m; i++) { int x = getint(),y,mi,sum; len = INF; Search(1,1,n,dfn[x],End[x]); if (len != INF) len -= Query(1,1,n,dfn[x]); y = now; mi = len; sum = A[x] >= 0 ? 1 : -1; for (int z = x >> 1,pos = x & 1; z; pos = z & 1,sum += A[z] >= 0 ? 1 : -1,z >>= 1) { int Nex = (z << 1) | (pos ^ 1); len = INF; if (c[z] > 0 && sum < mi) mi = sum,y = z; if (Nex > n) continue; Search(1,1,n,dfn[Nex],End[Nex]); if (len == INF) continue; len -= Query(1,1,n,dfn[z]); if (len + sum < mi) mi = len + sum,y = now; } Walk(x,y); Ans += mi; printf("%d ",Ans); } return 0;}
- 4849: [Neerc2016]Mole Tunnels
- BZOJ4849 [Neerc2016]Mole Tunnels
- bzoj 4849: [Neerc2016]Mole Tunnels 模拟费用流
- [bzoj4849]Mole Tunnels
- codeforces101190M——Mole Tunnels
- [模拟费用流] Codeforces Gym101190 NEERC2016M. Mole Tunnels
- mole
- mole
- [树形DP 费用流手动增广] Codeforces Gym 101190 NEERC 16 M. Mole Tunnels
- Maze&&Mole
- bzoj4846: [neerc2016]Hard Refactoring
- bzoj4839: [Neerc2016]Abbreviation
- SSH-Tunnels
- BZOJ4843 [Neerc2016]Expect to Wait
- Poj3034 Whac-a-Mole
- poj Whac-a-Mole
- POJ3034--Whac-a-Mole
- poj3034 Whac-a-Mole
- mybatis 返回基本类型
- 何处是故乡--读《中国在梁庄》
- 用docker安装YCM创建自己的vim开发环境
- Android studio 中NameValuePair跟BasicNameValuePair 不能正常导包问题
- android Apk打包过程概述
- 4849: [Neerc2016]Mole Tunnels
- Java Day02-1
- hdu 2016 数据的交换输出
- JavaScript面向对象(一)基础详解及封装
- spring boot集成rabbitmq
- Java多线程/并发07、Thread.Join()让调用线程等待子线程
- hadoop2.7.2学习笔记02-启动集群
- 整数用逗号隔开
- C#中的特性和反射