• 「SCOI2015」小凸玩密室 解题报告


    「SCOI2015」小凸玩密室

    虽然有心里在想一些奇奇怪怪的事情的原因,不过还是写太久了..

    不过这个题本身也挺厉害的

    注意第一个被点亮的是任意选的,我最开始压根没注意到

    (dp_{i,j})代表(i)号点子树最后连出去的一个点连的是它第(j)层的祖先

    (f_{i,j})代表(i)号点子树最后连出去的一个点连的是它第(j)层祖先的另一个儿子

    然后我们就可以拼子树,做换根了

    要讨论只有一个儿子的情况


    Code:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #define ll long long
    const int N=2e5+10;
    using std::min;
    template <class T>
    void read(T &x)
    {
    	x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    ll dp[2][N][20],a[N],edge[N],ans=1e18;
    int n,Log[N];
    #define ls (id<<1)
    #define rs (id<<1|1)
    void dfs(int id)
    {
    	if(id<<1>n) return;
    	dfs(ls),dfs(rs);
    	for(int dep=Log[id];~dep;dep--)
        {
            if(ls<=n&&rs<=n)
            {
                dp[0][id][dep]=min(a[ls]*edge[ls]+dp[1][ls][Log[id]]+dp[0][rs][dep]
                                  ,a[rs]*edge[rs]+dp[1][rs][Log[id]]+dp[0][ls][dep]);
                dp[1][id][dep]=min(a[ls]*edge[ls]+dp[1][ls][Log[id]]+dp[1][rs][dep]
                                  ,a[rs]*edge[rs]+dp[1][rs][Log[id]]+dp[1][ls][dep]);
            }
            else if(ls<=n)
            {
                dp[0][id][dep]=a[ls]*edge[ls]+dp[0][ls][dep];
                dp[1][id][dep]=a[ls]*edge[ls]+dp[1][ls][dep];
            }
        }
    }
    void dfs0(int id,ll cost)
    {
        ans=min(ans,dp[0][id][Log[id]-1]+cost);
        if(ls<=n&&rs<=n)
        {
            dfs0(ls,a[rs]*edge[rs]+dp[0][rs][Log[id]-1]+cost);
            dfs0(rs,a[ls]*edge[ls]+dp[0][ls][Log[id]-1]+cost);
        }
        else if(ls<=n)
            dfs0(ls,edge[id]*a[id>>1]+cost);
    }
    int main()
    {
    	int flag=0;read(n);
    	for(int i=1;i<=n;i++) read(a[i]),Log[i]=Log[i>>1]+1;
    	for(int i=2;i<=n;i++) read(edge[i]);
    	memset(dp,0x3f,sizeof dp);
    	for(int i=1;i<=n;i++)
    		if(i<<1>n)
    		{
    			int typ=!(i&1),id=i>>1;ll sum=edge[i];
    			for(int j=Log[i]-1;~j;j--)
    			{
    				dp[0][i][j]=a[id]*sum;
    				dp[1][i][j]=a[id<<1|typ]*(sum+edge[id<<1|typ]);
    				sum+=edge[id];
    				typ=!(id&1);
    				id>>=1;
    			}
    		}
    	dfs(1);
    	dfs0(1,0);
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    2019.2.27

  • 相关阅读:
    单独设置css的class属性
    理解闭包的使用方法
    npm常用命令和总结
    前端调试之服务器
    gulp 报错的处理——个人经验
    工作经验备忘
    c++:虚函数和纯虚函数(转载)
    snmp学习、配置
    sigar学习
    linux安装VSCode
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10445897.html
Copyright © 2020-2023  润新知