[NOI2006]网络收费
题面在这里
description
一棵\(2^n\)个叶节点的满二叉树,每个节点代表一个用户,有一个预先的收费方案\(A\)或\(B\);
对于任两个用户 \(i,j(1≤i<j≤2^n)i,j(1≤i<j≤2^n)\),首先在树上找到与它们距离最近的公共祖先\(P\),然后观察\(P\)所管辖的叶结点(即用户)中选择付费方式\(A\)与\(B\)的人数,分别记为\(n_A\)与\(n_B\) ,接着按下表进行收费,其中\(F_{i,j}\)为\(i\)和\(j\)之间的流量,且为已知量。
给定每个用户注册时所选择的付费方式以及修改收费方案的费用\(C_i\)(\(A\)修改为\(B\),\(B\)修改为\(A\)),试求这些用户的最小费用
data range
\]
solution
技不如人,甘拜下风
一开始看错了题目,以为只有两个相邻的用户才会产生收费,然后看到题目中输入了一个矩阵就\(mengbi\)了,赶紧换思路
然后分析了一下收费的规律,发现了一条很重要的性质:
当\(n_a < n_b\)时,
\(2个A->k=2\)
\(1个A->k=1\)
\(0个A->k=0\)
因此,
在一棵子树中,只有选择两种收费方案中少数的叶节点才会产生贡献,
并且这样的贡献是互不相关的
那么,
对于一个用户,他能否产生贡献取决于他的收费方案以及其祖先节点子树的收费情况
(\(n_a<n_b\)或\(n_a\ge n_b\))
对于这种贡献计算和叶节点到祖先路径有关的题目,
我们先预处理叶节点,然后在非叶节点上合并(HNOI2018已经吃过亏了)
在这里合并的时候,我们发现祖先收费情况只和\(n_a\)和\(n_b\)的有关,
因此我们需要记录人数,然后利用背包合并;
综上所述,我们需要记录子树位置,祖先的收费情况(一个二维向量),人数这三维,使用\(f[i][j][k]\)表示;
在做题的时候,笔者发现了以上的性质,但自己多想认为无法根据父节点的收费情况统计两棵子树的贡献,因此没有做出来,今后看题目还是需要入手一个小样例,让自己更加接近题目的本质
上转移方程;
我们先使用\(g[i][j]\)记录叶节点\(i\)在自己的第\(j\)个父亲作为\(LCA\)的时候和其他节点产生的收费之和;
之后有
\]
转移时对于不合法的状态(比如人数不符合子树要求)直接不作转移即可
这里笔者之前又有一个忧虑是转移是\(O(2^{4n})\)的(其实\(O(2^{4n})80\)分应该也可以过吧)
那么我们来看时间复杂度到底是多少
我们把这棵树按照深度分层,可以知道其层数不超过\(n(n\le 10)\)
而\([j][k]\)这两维在每一层的乘积是一定的,
因为每往下走一层,\(j\)就会\(\times 2\)(多一维向量),\(k\)就会\(\div 2\)(人数少了一半);
因此把\([j][k]\)压作一维,状态总数是\(O(2^{2n})\)的;
对于计算时的背包转移,每往下一层我们的转移会多一被,但\(t\)的枚举也少了一半,因此乘积还是\(O(2^{2n})\)的,共有\(n\)层,因此这里的时间复杂度是\(O(2^{2n}n)\);
因此总时间复杂度就是\(O(2^{2n}+2^{2n}n)\)。
改了两天半的惨痛教训
code
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "a"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e9+7;
const int N=3010;
const dd pi=acos(-1);
const int inf=2147483647;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
}
int n,w[N],c[N],d[N][N],g[N][N],f[N][N],ans;
#define mid ((l+r)>>1)
void init(int dep,int l,int r){
if(l==r)return;
for(RG int i=l;i<=mid;i++)g[dep][i]=d[i][r]-d[i][mid];
for(RG int i=mid+1;i<=r;i++)g[dep][i]=d[i][mid]-d[i][l-1];
init(dep+1,l,mid);init(dep+1,mid+1,r);
}
int dfs(int x,int y,int z,int dep){
if(f[x][(y<<dep)|z]!=-1){
return f[x][(y<<dep)|z];
}
int sum;
if(dep==n){
RG int now=x-(1<<n)+1,zz=z;
sum=c[now]*(w[now]==y);
for(RG int i=dep-1;~i;i--,zz>>=1)
if((zz&1)!=y)sum+=g[i][now];
return f[x][(y<<dep)|z]=sum;
}
else{
sum=inf;int p=(y>=(1<<(n-dep-1)));
for(RG int i=max(0,y-(1<<(n-dep-1)));i<=min(y,1<<(n-dep-1));i++)
sum=min(sum,dfs(x<<1,i,z<<1|p,dep+1)+dfs(x<<1|1,y-i,z<<1|p,dep+1));
return f[x][(y<<dep)|z]=sum;
}
}
int main()
{
n=read();
for(RG int i=1;i<=(1<<n);i++)w[i]=read();
for(RG int i=1;i<=(1<<n);i++)c[i]=read();
for(RG int i=1;i<(1<<n);i++)
for(RG int j=i+1;j<=(1<<n);j++)
d[i][j]=d[j][i]=read();
for(RG int i=1;i<=(1<<n);i++)
for(RG int j=1;j<=(1<<n);j++)
d[i][j]+=d[i][j-1];
init(0,1,(1<<n));ans=inf;memset(f,-1,sizeof(f));
for(RG int i=0;i<=(1<<n);i++)
ans=min(ans,dfs(1,i,0,0));
printf("%d\n",ans);
return 0;
}
[NOI2006]网络收费的更多相关文章
- 【BZOJ1495】[NOI2006]网络收费 暴力+DP
[BZOJ1495][NOI2006]网络收费 Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的一点就是网络本身有 ...
- 洛谷 P4297 [NOI2006]网络收费
P4297 [NOI2006]网络收费 题目背景 noi2006 day1t1 题目描述 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的 ...
- BZOJ_1495_[NOI2006]网络收费_树形DP
BZOJ_1495_[NOI2006]网络收费_树形DP Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而, 不可忽视的一点就 ...
- 并不对劲的[noi2006]网络收费
题目略长,就从大视野上复制了. 听上去好像费用流,然而…… ***************************表示略长的题目的分界线************************ 1495: [ ...
- 【简】题解 P4297 [NOI2006]网络收费
传送门:P4297 [NOI2006]网络收费 题目大意: 给定一棵满二叉树,每个叶节点有一个状态(0,1),任选两个叶节点,如果这两个叶节点状态相同但他们的LCA所管辖的子树中的与他们状态相同的叶节 ...
- 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp
LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...
- 【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp
题目描述 给出一个有 $2^n$ 个叶子节点的完全二叉树.每个叶子节点可以选择黑白两种颜色. 对于每个非叶子节点左子树中的叶子节点 $i$ 和右子树中的叶子节点 $j$ :如果 $i$ 和 $j$ 的 ...
- BZOJ1495 [NOI2006]网络收费
题意 传送门 MY市NS中学,大概是绵阳市南山中学. 分析 参照Maxwei_wzj的题解. 因为成对的贡献比较难做,我们尝试把贡献算到每一个叶子节点上.我们发现按照题目中的收费方式,它等价于对于每棵 ...
- BZOJ1495 [NOI2006]网络收费 【树形dp + 状压dp】
题目链接 BZOJ1495 题解 观察表格,实际上就是分\(A\)多和\(B\)两种情况,分别对应每个点选\(A\)权值或者\(B\)权值,所以成对的权值可以分到每个点上 所以每个非叶节点实际对应一个 ...
随机推荐
- Linux下安装Nginx并实现socket代理
nginx可以使用各平台的默认包来安装,本文是介绍使用源码编译安装,包括具体的编译参数信息. 正式开始前,编译环境gcc g++ 开发库之类的需要提前装好,这里默认你已经装好. ububtu平台编译环 ...
- android 学习四 ContentProvider
1.系统自带的许多数据(联系人,本地信息等)保存在sqllite数据库,然后封装成许多ContentProvider来供其他程序访问. 2.对sqllite数据库的操作,可以在命令行通过adb工具登录 ...
- 说一说VIN码识别,车架号识别那些事
对于有车一族的朋友来说,日常接触比较多的是车牌.行驶证.驾驶证,而知道VIN码/车架号码的比较少. 其实,对于车辆来说,VIN码/车架号码非常重要,它就像人的身份证一样,VIN码/车架号码是车辆唯一的 ...
- Swift使用AVAudioPlayer来调节游戏的背景音乐大小
音乐文件的声音大小有时在做为游戏背景音乐时会过大,而如果我们只是简单应用SKAudioNode来加载音乐的话,是无法进行声音大小的调节的,因此我们必须使用更强大的AVAudioPlayer来进行声音大 ...
- 域名、IP地址、URL关系
域名是个文字形式记录的IP地址 IP地址是计算机在网络中的门牌号! URL是网页地址 例如1: http://zhidao.baidu.com/question/14674128.html 是URL ...
- python 终极篇 --- form组件 与 modelForm
form组件 ...
- 181. Flip Bits【LintCode, by java】
Description Determine the number of bits required to flip if you want to convert integer n to intege ...
- python 文件编译成exe可执行文件。
pyinstaller打包方法: pyinstaller安装参考地址:http://www.pyinstaller.org/ pywin32的下载地址:https://sourceforge.net/ ...
- 洛谷P1068 分数线划定:sort结构体排序+贪心
题目描述 世博会志愿者的选拔工作正在 A 市如火如荼的进行.为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试. 面试分数线根据计划录取人数的150%划定, ...
- Juice账号
zhangxiaocong69 zxc6545398 15657167502 区块链账户: 0x00680404766965143796a0a070835c3cdf9a4a50