「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\n",ans);
    return 0;
}

2019.2.27

猜你喜欢

转载自www.cnblogs.com/butterflydew/p/10445897.html