小凸玩密室题解

小凸玩密室题解

恶心题啊~~
开始连题意都看不懂,
看了会题解的题意简化,结果理解错了题意,说多了都是泪啊~
首先说说题意吧:
点亮一盏灯后,只有点亮完子树内所有灯后才能点其他灯,而且点亮的灯要求要连通。
-->下一步一定点两个儿子之一,先点完这个儿子的子树再点另一个儿子。
然而,上一盏灯点什么十分不好求,贡献算不出(一个点子树内有多个层数相同的子孙)。
但是,我们可以通过上一盏灯算下一盏灯的贡献啊(每个点只有一个层数一定的父辈)。
所以点完这个点后,我们只有两种情况:
1.我们点完这个点后构成了一棵子树,我们下一步只可能点子树的根的父亲(点亮的灯要连通)。
2.点完了一棵子树加上其根的父亲,下一步一定点另一棵子树
并且,我们注意看题,发现:
什么?完全二叉树--->层数\((log2 n)\)
于是我们设\(dp\)状态:
\(f[i][j][0]:\)先点完\(i\)的子树,然后先点\(i\)的第\(j\)个父亲的最小值;
\(f[i][j][1]:\)先点完\(i\)的子树,然后先点\(i\)的第\(j\)个父亲的另一个儿子的最小值。
并要预处理:\(dis[i][j]\)表示第\(i\)个点到第\(j\)个祖先的边权值
怎么转移?
分三种情况讨论:
注:下面\((i>>j)\)表示第\(i\)个点的第\(j\)个祖先的编号,\((i>>(j-1))^1\)表示第\(i\)个点第\(j\)个祖先的另一个儿子的编号。
1.一个儿子也没有:即\(((i<<1)>n)\)
只可能从它结束到祖先。
\(f[i][j][0]=dis[i][j]*num[i>>j],f[i][j][1]=(dis[i][j]+dis[(i>>(j-1))^1][1])*num[(i>>(j-1))^1]\)
2.如果只有一个儿子(左儿子):即\((i<<1|1)>n\)
必须从儿子继承。
\(f[i][j][0]=dis[i<<1][1]*w[i<<1]+f[i<<1][j+1][0],f[i][j][1]=dis[i<<1][1]*w[i<<1]+f[i<<1][j+1][1]\)
2.如果有两个儿子:
那么可以先左后右,或者先右后左。
\(f[i][j][0]=min(f[i][j][0],f[i<<1][1][1]+f[i<<1|1][j+1][0]+dis[i<<1][1]*w[i<<1])\)
\(f[i][j][0]=min(f[i][j][0],f[i<<1][j+1][0]+f[i<<1|1][1][1]+dis[i<<1|1][1]*w[i<<1|1])\)
\(f[i][j][1]=min(f[i][j][1],f[i<<1][1][1]+f[i<<1|1][j+1][1]+dis[i<<1][1]*w[i<<1])\)
\(f[i][j][1]=min(f[i][j][1],f[i<<1][j+1][1]+f[i<<1|1][1][1]+dis[i<<1|1][1]*w[i<<1|1])\)
最后,我们只要确定了一个起始点,点亮顺序便确定了,按顺序点灯,答案取最小值即可。

#include<bits/stdc++.h>
#define ll long long
#define lc (i<<1)
#define rc (i<<1|1)
using namespace std;
const int N=2e5+7;
int n,lat;
ll tmp=0,ans=9e18+7,w[N],f[N][20][2],dis[N][20];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
int main(){
   n=read(),memset(f,0x3f,sizeof(f));
   for(int i=1;i<=n;++i) w[i]=read();
   for(int i=2;i<=n;++i){
       dis[i][1]=read();
       for(int j=2;(1<<(j-1))<=i;++j) dis[i][j]=dis[i>>1][j-1]+dis[i][1];
   }
   for(int i=n;i>=1;--i)
      for(int j=1;(1<<(j-1))<=i;++j){
          if(lc>n) f[i][j][0]=dis[i][j]*w[i>>j],f[i][j][1]=(dis[i][j]+dis[(i>>(j-1))^1][1])*w[(i>>(j-1))^1];
          else if(rc>n) f[i][j][0]=dis[lc][1]*w[lc]+f[lc][j+1][0],f[i][j][1]=dis[lc][1]*w[lc]+f[lc][j+1][1];
          else{
             f[i][j][0]=min(f[i][j][0],f[lc][1][1]+f[rc][j+1][0]+dis[lc][1]*w[lc]),f[i][j][0]=min(f[i][j][0],f[lc][j+1][0]+f[rc][1][1]+dis[rc][1]*w[rc]);
             f[i][j][1]=min(f[i][j][1],f[lc][1][1]+f[rc][j+1][1]+dis[lc][1]*w[lc]),f[i][j][1]=min(f[i][j][1],f[lc][j+1][1]+f[rc][1][1]+dis[rc][1]*w[rc]);
          }
      }
   for(int i=1;i<=n;++i){
       tmp=f[i][1][0],lat=i;
       for(int j=(i>>1);j;j>>=1){
           if((lat^1)<=n) tmp+=dis[lat^1][1]*w[lat^1]+f[lat^1][2][0];
           else tmp+=dis[j][1]*w[j>>1];
           lat=j;
       }
       ans=min(ans,tmp);
   }
   printf("%lld\n",ans);
   return 0;
}

原文地址:https://www.cnblogs.com/ljk123-de-bo-ke/p/11832248.html

时间: 2024-08-01 21:49:59

小凸玩密室题解的相关文章

[BZOJ4446]SCoi2015 小凸玩密室 树形DP(烧脑高能预警)

4446: [Scoi2015]小凸玩密室 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 个(1个)新的灯泡V的花费,等于上一个被点亮的灯泡U到这个点V的距离Du,v,乘以这个点的权值Av.在点灯 的过程中,要保证任意时刻所有被点亮的灯泡必须连

LibreOJ #2009. 「SCOI2015」小凸玩密室

二次联通门 : LibreOJ #2009. 「SCOI2015」小凸玩密室 /* LibreOJ #2009. 「SCOI2015」小凸玩密室 树形dp 做到这么正常的题突然感觉好不适应.... 考虑转移 f[x][y] 表示从x点转移到y点的代价 则我们需要处理出以x为根的子树的代价 讨论处理一下即可(有没有左儿子,有没有右儿子,或是都有) 但是这样转移是O(N^2)的 所以我们考虑优化 显然有很多转移是不需要的 比如y在x的子树中时就没必要转移 那么考虑优化 设g[x][i]表示走完x的子

—Libre#2009. 「SCOI2015」小凸玩密室

#2009. 「SCOI2015」小凸玩密室 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方相约玩密室逃脱,这个密室是一棵有 n nn 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 Ai A_iA?i??,每条边也有个权值 bi b_ib?i??. 点亮第 1 11 个灯泡不需要花费,之后每点亮一个新的灯泡 V VV 的花费,等于上一个被点亮的

bzoj4446[Scoi2015]小凸玩密室

4446: [Scoi2015]小凸玩密室 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 419  Solved: 173[Submit][Status][Discuss] Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要花费,之后每点亮4 个新的灯泡V的花费,等于上一个被点亮的灯泡U到这个点V的

「SCOI2015」小凸玩密室

题目描述 小凸和小方相约玩密室逃脱,这个密室是一棵有 $n$ 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 $A_i$,每条边也有个权值 $b_i$. 点亮第 $1$ 个灯泡不需要花费,之后每点亮一个新的灯泡 $V$ 的花费,等于上一个被点亮的灯泡 $U$ 到这个点 $V$ 的距离 $D(u, v)$,乘以这个点的权值 $A_v$. 在点灯的过程中,要保证任意时刻所有被点亮的灯泡必须连通,在点亮一个灯泡后必须先点亮其子树所有灯泡才能点亮其他灯泡.请告诉他们,

[bzoj4446] [loj#2009] [Scoi2015] 小凸玩密室

Description 小凸和小方相约玩密室逃脱,这个密室是一棵有 \(n\) 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 \(Ai\) ,每条边也有个权值 \(bi\) .点亮第 1 个灯泡不需要花费,之后每点亮 1 个新的灯泡 \(V\) 的花费,等于上一个被点亮的灯泡 \(U\) 到这个点 \(V\) 的距离 \(Du,v\),乘以这个点的权值 \(Av\) .在点灯的过程中,要保证任意时刻所有被点亮的灯泡必须连通,在点亮一个灯泡后必须先点亮其子树所

【BZOJ4443】[Scoi2015]小凸玩矩阵 二分+二分图最大匹配

[BZOJ4443][Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<

4443: [Scoi2015]小凸玩矩阵

4443: [Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<=K&l

[Scoi2015]小凸玩矩阵

bzoj 4443: [Scoi2015]小凸玩矩阵 http://www.lydsy.com/JudgeOnline/problem.php?id=4443 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N