• P3262 [JLOI2015]战争调度


    题解

    由于这是一棵满二叉树,所以其树高只有 (n)

    (f_{i,j,S})(i) 的子树内,有 (j) 个平民参战,且 (operatorname{fa}(i)sim 1) 的路径上的点,颜色为 (S) 的对应二进制位。转移就是普通的树上背包。

    乍一看时间复杂度不太对,但 (f) 只有 (sum_{i=1}^n 2^i imes 2^{n-i} imes 2^i) 个状态;一个状态 ((i,j,S)) 的转移复杂度是 (mathcal{O}(j))。于是总复杂度是 (mathcal{O}(n4^n))

    但这样 (f) 比较难存储,发现可以把 (S) 通过 dfs 砍掉。

    Bonus:应该可以通过上下界优化,让时间复杂度变成 (mathcal{O}(4^n))

    代码

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
    #define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
    template<typename T>
    void Read(T &_x){
    	_x=0;int _f=1;
    	char ch=getchar();
    	while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();
    	while(isdigit(ch)) _x=_x*10+(ch^48),ch=getchar();
    	_x*=_f;
    }
    template<typename T,typename... Args>
    void Read(T &_x,Args& ...others){
    	Read(_x);Read(others...);
    }
    typedef long long ll;
    const int Vertex=1030;
    int n,m,son[Vertex][2],fa[Vertex],dep[Vertex],cont[Vertex][Vertex][2];
    ll f[Vertex][Vertex];
    void Dfs(int u,int stat){
    	memset(f[u],0,sizeof(f[u]));
    	if(!son[u][0]){
    		for(int v=fa[u],st=stat;v;v=fa[v],st>>=1){
    			if(st&1) f[u][1]+=cont[u][v][1];
    			else f[u][0]+=cont[u][v][0];
    		}
    		return;
    	}
    	For(i,0,1){
    		Dfs(son[u][0],stat<<1|i);
    		Dfs(son[u][1],stat<<1|i);
    		int mx=(1<<(n-dep[u]));
    		For(j,0,min(mx,m)){
    			For(k,0,j){
    				f[u][j]=max(f[u][j],f[son[u][0]][k]+f[son[u][1]][j-k]);
    			}
    		}
    	}
    }
    int main(){
    	Read(n,m);
    	For(i,1,(1<<(n-1))-1) son[i][0]=i<<1,son[i][1]=i<<1|1;
    	For(i,1,(1<<n)-1) fa[i]=i/2,dep[i]=dep[fa[i]]+1;
    	For(i,1,1<<(n-1)){
    		int u=(1<<(n-1))+i-1,v=fa[u];
    		For(j,1,n-1){
    			int x;Read(x);
    			cont[u][v][1]=x;
    			v=fa[v];
    		}
    	}
    	For(i,1,1<<(n-1)){
    		int u=(1<<(n-1))+i-1,v=fa[u];
    		For(j,1,n-1){
    			int x;Read(x);
    			cont[u][v][0]=x;
    			v=fa[v];
    		}
    	}
    	Dfs(1,0);
    	ll ans=0;
    	For(i,0,m) ans=max(ans,f[1][i]);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    Written by Alan_Zhao
  • 相关阅读:
    读写锁操作(ReaderWriterLockSlim)
    VirtualBox的小秘密:命令行
    云的始祖概念,认识Linux瘦客户机
    Flash ActionScript 3.0 通过asp.net 访问 数据库
    js刷新iframe框架的几种情况分析
    Mozilla两款火狐插件包含恶意代码被紧急喊停
    asp.net中DataBinder.Eval的用法总结
    实现firebird的Embedded模式(.net 3.5)
    Flash Player 9 支持H.264视频和aac音频(附官方代码)
    右下角浮动广告代码DEMO
  • 原文地址:https://www.cnblogs.com/alan-zhao-2007/p/p3262-sol.html
Copyright © 2020-2023  润新知