题意

传送门

MY市NS中学,大概是绵阳市南山中学。

分析

参照Maxwei_wzj的题解。

因为成对的贡献比较难做,我们尝试把贡献算到每一个叶子节点上。我们发现按照题目中的收费方式,它等价于对于每棵子树,A和B哪个更少,就统计这样的贡献:对于每个这种类型的用户\(i\),如果\(i,j\)的LCA是当前子树的根,则累计\(F(i,j)\)。

为什么等价呢?因为观察计费形式,



假设A更少,那么对所有满足LCA为当前根的点对\((i,j)\),如果两个同为A,则累计两次\(F(i,j)\),等价于累计\(F(i,j)\)和\(F(j,i)\)各一次,如果其中有一个为A,那么要么累计\(F(i,j)\),要么累计\(F(j,i)\),累计的是为A的那个,因此两种计算方式是可以归纳总结的。注意到满足LCA相同的条件的\(j\)一定是一个连续区间,因此我们可以预处理出前缀和,加快询问的速度。

接下来就要考虑状态转移了。我们发现在每个点上实际上是在做这样的决策:要使A更少还是使B更少。而我们发现,一个点的贡献受且仅受它的祖先决策的影响。注意到深度只有\(n\),所以我们可以在状态中开一维表示该点祖先的决策状态,最多有\(2^n\)种。那么我们可以得到一个状态定义,如下:

令\(f(i,j,k)\)为以点\(i\)为根的子树中,点ii的祖先的决策状态为\(j\),子树中有\(k\)个A时,能得出的最小花费。

当点\(i\)为叶子节点时,我们可以借助前缀和\(O(n)\)算出这个状态的花费,而其他点的状态就类似线段树和背包一样合并子节点转移即可,可以证明时间复杂度为\(\Omega(2^{2n}),o(2^{3n})\)。

还有一点要注意,直接开\(f(i,j,k)\)的话,空间复杂度为\(O(2^{3n})\),无法接受,注意到在深度为\(dep\)时,\(j\)最多有\(2^{dep}\)种决策,而\(k\)最大为\(2^{n−dep}\),那么如果我们把这两维合并成一维,那么这一维从始至终最多有\(2^n\)种组合,那么我们就把空间复杂度也优化到了\(O(2^{2n})\),可以通过此题。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
template<class T>T read(T&x)
{
return x=read<T>();
}
using namespace std;
typedef long long ll;
co ll INF=0x3f3f3f3f3f3f3f3f; co int MAXN=10;
int n;
bool type[1<<MAXN|7];
ll c[1<<MAXN|7],sum[1<<MAXN|7][1<<MAXN|7];
ll f[1<<(MAXN+1)|7][1<<(MAXN+1)|7]; ll calc(int x,int opt,bool type)
{
int l=1,r=(1<<n),dep=n-1;
ll res=0;
while(l<r)
{
int m=(l+r)>>1;
if(x<=m)
{
if(type==((opt>>dep)&1)) // 如果类型和少的相同
res+=sum[x][r]-sum[x][m];
r=m;
}
else
{
if(type==((opt>>dep)&1))
res+=sum[x][m]-sum[x][l-1];
l=m+1;
}
--dep;
}
return res;
} void dp(int x,int dep)
{
if(!dep) // 叶子节点
{
for(int i=0;i<(1<<n);++i)
{
f[x][i*(1<<(dep+1))+0]=calc(x-(1<<n)+1,i,1);
f[x][i*(1<<(dep+1))+1]=calc(x-(1<<n)+1,i,0);
f[x][i*(1<<(dep+1))+type[x-(1<<n)+1]]+=c[x-(1<<n)+1];
}
return;
}
dp(x<<1,dep-1);
dp(x<<1|1,dep-1);
for(int i=0;i<(1<<(n-dep));++i)
for(int j=0;j<=(1<<dep);++j) // 枚举0的数量
{
int s=i*(1<<(dep+1))+j;
f[x][s]=INF;
bool flag=(j>=(1<<dep)-j); // 那种类型更少
int ns=i*(1<<(dep+1))+flag*(1<<dep);
for(int k=0;k<=j;++k) // 枚举左儿子0的数量
if(k<=(1<<(dep-1))&&j-k<=(1<<(dep-1))) // 数量要在左右儿子容纳范围内
f[x][s]=min(f[x][s],f[x<<1][ns+k]+f[x<<1|1][ns+j-k]);
}
} void init()
{
read(n);
for(int i=1;i<=(1<<n);++i)
read(type[i]);
for(int i=1;i<=(1<<n);++i)
read(c[i]);
for(int i=1;i<=(1<<n);++i)
{
sum[i][i]=0;
for(int j=i+1;j<=(1<<n);++j)
sum[j][i]=read(sum[i][j]);
}
for(int i=1;i<=(1<<n);++i)
{
sum[i][0]=0;
for(int j=1;j<=(1<<n);++j)
sum[i][j]+=sum[i][j-1];
}
} int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
init();
dp(1,n);
ll ans=INF;
for(int i=0;i<=(1<<n);++i)
ans=min(ans,f[1][i]);
printf("%lld\n",ans);
return 0;
}

BZOJ1495 [NOI2006]网络收费的更多相关文章

  1. BZOJ1495 [NOI2006]网络收费 【树形dp + 状压dp】

    题目链接 BZOJ1495 题解 观察表格,实际上就是分\(A\)多和\(B\)两种情况,分别对应每个点选\(A\)权值或者\(B\)权值,所以成对的权值可以分到每个点上 所以每个非叶节点实际对应一个 ...

  2. bzoj1495 [NOI2006]网络收费 复杂度分析+树上背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1495 题解 通过观察可以发现,对于一个 \(lca\),如果 \(nA \leq nB\),那 ...

  3. 【BZOJ1495】[NOI2006]网络收费 暴力+DP

    [BZOJ1495][NOI2006]网络收费 Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的一点就是网络本身有 ...

  4. 洛谷 P4297 [NOI2006]网络收费

    P4297 [NOI2006]网络收费 题目背景 noi2006 day1t1 题目描述 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的 ...

  5. BZOJ_1495_[NOI2006]网络收费_树形DP

    BZOJ_1495_[NOI2006]网络收费_树形DP Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而, 不可忽视的一点就 ...

  6. 并不对劲的[noi2006]网络收费

    题目略长,就从大视野上复制了. 听上去好像费用流,然而…… ***************************表示略长的题目的分界线************************ 1495: [ ...

  7. 【简】题解 P4297 [NOI2006]网络收费

    传送门:P4297 [NOI2006]网络收费 题目大意: 给定一棵满二叉树,每个叶节点有一个状态(0,1),任选两个叶节点,如果这两个叶节点状态相同但他们的LCA所管辖的子树中的与他们状态相同的叶节 ...

  8. 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp

    LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...

  9. 【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp

    题目描述 给出一个有 $2^n$ 个叶子节点的完全二叉树.每个叶子节点可以选择黑白两种颜色. 对于每个非叶子节点左子树中的叶子节点 $i$ 和右子树中的叶子节点 $j$ :如果 $i$ 和 $j$ 的 ...

随机推荐

  1. 《Think in Java》(十四)类型信息

    简介 RTTI,RunTime Type Information,运行时类型信息.Java 在运行时识别对象和类的信息主要有两种方式:一种是"传统的"RTTI,它假定我们在编译时已 ...

  2. spring mvc: 生成RSS源

    spring mvc: 生成RSS源 准备: 从相同的maven存储库页面下载 Rome 库及其依赖项rome-utils,jdom和slf4j.和所需的依赖关系 <!-- rss源依赖 --& ...

  3. uva10766生成树计数

    此类题是给定一个无向图,求所有生成树的个数,生成树计数要用到Matrix-Tree定理(Kirchhoff矩阵-树定理) G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0:当i ...

  4. Less开发指南(二)- 基本语法

    (一)嵌套规则 [1]less可以让我们以嵌套的方式编写层叠样式,先看下面这段CSS: .box-a .hd { height: 20px; } .box-a .bd .txt { color: #0 ...

  5. iOS-如何写好一个UITableView

    如何写好一个UITableView 字数5787 阅读3745 评论25 喜欢69 本文是直播分享的简单文字整理,直播共分为上.下两部分.第一部分:优酷 Or YouTube,第二部分:优酷 Demo ...

  6. Web字体(链接)嵌入

    下面是我最近在学习的两种字体嵌入方法 1.@font-face 使用@font-face可以这样做: @font-face{ font-family:"Garamod Premier Pro ...

  7. 华为EPON OLT开局配置

      配置思路: 1. 登录olt(console进去之后配地址) 2.配置上联口(配vlan和起三层地址互联路由的lan口) 3.epon接分光器,分光器下接光猫 4.自动发现光猫.配置DBA数据和线 ...

  8. ES6入门之对象扩展

    ES5对象(超类)原有: 属性:construct构造函数 方法: object.hasOwnProperty( propertyName ) //检测是否有一个本地的属性而不是继承的,返回boole ...

  9. GPU编程自学5 —— 线程协作

    深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ...

  10. CUDA Samples: heat conduction(模拟热传导)

    以下CUDA sample是分别用C++和CUDA实现的模拟热传导生成的图像,并对其中使用到的CUDA函数进行了解说,code参考了<GPU高性能编程CUDA实战>一书的第七章,各个文件内 ...