BJ 集训测试14 bird
2018-03-30 22:21
489 查看
http://www.elijahqi.win/archives/2831
题意:给一棵满二叉树 给定一些点有可以出去的容量 每次给你一个点 然后给这个点一个流量 路径边长都是1 请问如何花费最少的代价使得所有流量都从出点出去
一个显然的做法是每次动态加边然后跑费用流 但是考试的时候发现会有负环 怎么办 我考虑了种贪心的思路 首先若一个点的流量之前已经出去那么就不可能退流我就把这个之前做过的点的退流边全都删了就不存在负环了
正解:利用树高只有log然后手动模拟费用流过程
针对每个节点记录所管辖子树的可用点到我这里的最小值 以及编号还有我节点和父亲的边是否有流量经过是正的流量还是负的流量 然后每次新加一个点就暴力跳模拟费用流运行过程即可
题意:给一棵满二叉树 给定一些点有可以出去的容量 每次给你一个点 然后给这个点一个流量 路径边长都是1 请问如何花费最少的代价使得所有流量都从出点出去
一个显然的做法是每次动态加边然后跑费用流 但是考试的时候发现会有负环 怎么办 我考虑了种贪心的思路 首先若一个点的流量之前已经出去那么就不可能退流我就把这个之前做过的点的退流边全都删了就不存在负环了
正解:利用树高只有log然后手动模拟费用流过程
针对每个节点记录所管辖子树的可用点到我这里的最小值 以及编号还有我节点和父亲的边是否有流量经过是正的流量还是负的流量 然后每次新加一个点就暴力跳模拟费用流运行过程即可
#include<cstdio> #include<cstring> #include<algorithm> #define N 330000 #define lc x<<1 #define rc x<<1|1 #define ll long long #define inf 0x3f3f3f3f using namespace std; inline char gc(){ static char now[1<<16],*S,*T; if (T==S) {T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();} while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc(); return x*f; } const int OUT_LEN = 1024 * 1024; char obuf[OUT_LEN], *oh = obuf; inline void write_char(char c) { if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf; *oh++ = c; } template<class T> inline void W(T x) { static int buf[30], cnt; if (x == 0) write_char('0'); else { if (x < 0) write_char('-'), x = -x; for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48; while (cnt) write_char(buf[cnt--]); } } inline void flush() { fwrite(obuf, 1, oh - obuf, stdout); } struct node{ int y,next; }data[N<<1]; int h ,num,id ,mark ,c ,p ,n,m,mn ;ll ans; inline void dfs(int x){ if(x>n) return;if(c[x]) mn[x]=0,id[x]=x; dfs(lc);dfs(rc); if ((lc)<=n)if (mn[lc]+1<mn[x]) mn[x]=mn[lc]+1,id[x]=id[lc]; if ((rc)<=n)if (mn[rc]+1<mn[x]) mn[x]=mn[rc]+1,id[x]=id[rc]; } inline void update(int x){ if ((lc)<=n) if (mn[lc]+1-2*(mark[lc]>0)<mn[x]) mn[x]=mn[lc]+1-2*(mark[lc]>0),id[x]=id[lc]; if ((rc)<=n) if (mn[rc]+1-2*(mark[rc]>0)<mn[x]) mn[x]=mn[rc]+1-2*(mark[rc]>0),id[x]=id[rc]; } inline void add(int pos){ int mn1=inf,x=pos,d=0,lca; while(x) { if(mn1>d+mn[x]) mn1=d+mn[x],lca=x; ++d;d-=2*(mark[x]<0);x>>=1; }x=pos;ans+=mn1; for (int i=pos;i!=lca;i>>=1) ++mark[i]; for (int i=id[lca];i!=lca;i>>=1) --mark[i]; x=id[lca];--c[x];if (!c[x]) mn[x]=inf,id[x]=0; for (int i=x;i;i>>=1) { if (c[i]) {mn[i]=0,id[i]=i;continue;}mn[i]=inf;update(i); } for (int i=pos;i;i>>=1){ if (c[i]) {mn[i]=0;id[i]=i;continue;}mn[i]=inf;update(i); } } int main(){ freopen("t1.in","r",stdin); n=read();m=read();memset(mn,0x3f,sizeof(mn)); for (int i=1;i<=n;++i) c[i]=read(); for (int i=1;i<=m;++i) p[i]=read();dfs(1); for (int i=1;i<=m;++i) add(p[i]),W(ans),write_char(' ');flush(); return 0; }
相关文章推荐
- BJ 集训测试14 pow
- BJ 集训测试7 Mythological VII
- BJ 集训测试6 求和
- BJ 集训测试9 draw
- BJ 集训测试11 捕鱼
- BJ 集训测试12 同构
- BJ 集训测试10 城市
- BJ 集训测试12 coin
- BJ 集训测试10 序列
- BJ 集训测试13 钢琴
- BJ 集训测试13 平行
- BJ 集训测试11 level&& codeforces 700E
- BJ 集训测试11 flow
- BJ 集训8 测试 B 新访问计划
- BJ 集训测试9 Problem C King
- BJ 集训测试8 Problem C 插线板
- BJ 集训测试7 A模型
- 2016级移动应用开发在线测试14-MediaPlayer
- 2011百度实习生招聘笔试试题---软件测试—测试方向(BJ)
- OpenWrt下基于Bird的AdHoc无线多跳网络组建与测试