zoukankan      html  css  js  c++  java
  • BZOJ 4849 [NEERC2016]Mole Tunnels (模拟费用流)

    题目链接

    https://www.lydsy.com/JudgeOnline/problem.php?id=4849

    题解

    其实也是模拟费用流,但是这道题和一般的题目不一样,这道题是在一个完全二叉树上
    这意味着我们根本不需要考虑什么类似数轴上老鼠进洞之类的做法,我们跑费用流,每次选一条最短路增广即可
    然后增广之后最短路上的点费用会由(1)变成(-1), 直接在完全二叉树上暴力修改暴力维护子树内最近的食物点即可
    说白了就是暴力,但是复杂度(O(nlog n)).

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cassert>
    #include<iostream>
    using namespace std;
     
    inline int read()
    {
    	int x=0; bool f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    	for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
    	if(f) return x;
    	return -x;
    }
    
    const int N = 1e5;
    const int INF = 1e8;
    struct Element
    {
    	int x,pos;
    	Element() {}
    	Element(int _x,int _pos) {x = _x,pos = _pos;}
    };
    void update(Element &x,Element y) {if(y.x<x.x) x = y;}
    Element dp[N+3];
    int w[N+3];
    int pos[N+3];
    int dep[N+3];
    int c[N+3];
    int n,m;
     
    int LCA(int u,int v)
    {
    	while(u!=v)
    	{
    		if(u>v) u>>=1;
    		else v>>=1;
    	}
    	return u;
    }
    
    void pushup(int u)
    {
    	if(w[u]>0) {dp[u] = Element(0,u);}
    	else {dp[u] = Element(INF,0);}
    	if((u<<1)<=n) {update(dp[u],Element(dp[u<<1].x+(c[u<<1]<0?-1:1),dp[u<<1].pos));}
    	if((u<<1|1)<=n) {update(dp[u],Element(dp[u<<1|1].x+(c[u<<1|1]<0?-1:1),dp[u<<1|1].pos));}
    //	printf("pushup dp[%d]=(%d,%d)
    ",u,dp[u].x,dp[u].pos);
    }
     
    Element query(int u)
    {
    	Element ret(INF,0); int tmp = 0;
    	while(u)
    	{
    		update(ret,Element(dp[u].x+tmp,dp[u].pos));
    		tmp += c[u]>0?-1:1;
    		u>>=1;
    	}
    	return ret;
    }
     
    void addval(int u,int v,int x)
    {
    	while(u!=v)
    	{
    		c[u] += x;
    		pushup(u>>1);
    		u>>=1;
    	}
    	while(u>0)
    	{
    		pushup(u);
    		u>>=1;
    	}
    }
     
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1; i<=n; i++) scanf("%d",&w[i]);
    	for(int i=1; i<=m; i++) scanf("%d",&pos[i]);
    	dep[1] = 1; for(int i=2; i<=n; i++) dep[i] = dep[i>>1]+1;
    	for(int i=n; i>=1; i--) pushup(i);
    	int ans = 0;
    	for(int i=1; i<=m; i++)
    	{
    		int u = pos[i];
    		Element tmp = query(u);
    		ans += tmp.x; int v = tmp.pos,lca = LCA(u,v);
    		w[v]--; pushup(v);
    		addval(u,lca,-1);
    		addval(v,lca,1);
    		printf("%d ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    深入浅出JMS(二)--ActiveMQ简单介绍以及安装
    redis学习
    浏览器的渲染过程
    http请求
    常用正则表达式
    js继承的几种实现方式
    js中的浅拷贝和深拷贝
    webpack常用的plugin
    linux基本命令
    webpack压缩代码组件uglifyjs-webpack-plugin
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11346415.html
Copyright © 2011-2022 走看看