[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\)权值,所以成对的权值可以分到每个点上 所以每个非叶节点实际对应一个 ...
随机推荐
- LeetCode: 31. Next Permutation (Medium)
1. 原题链接 https://leetcode.com/problems/next-permutation/description/ 2. 题目要求 给出一个整型数组,让我们给出下一个排序情况.注意 ...
- mysql 常用语句使用
1.查询语句 SELECT * FROM table 2.更改语句 UPDATE table SET name = '123456' WHERE id = 100 3.插入语句 INSERT INTO ...
- 用最简单的MVC模式输出内容
MVC是模型(model)-视图(view)-控制器(controller)的缩写,它的作用是使代码分离,可维护性高.重用性高 编写Model层: <?php class model{ publ ...
- TW实习日记:第16天
前端的样式bug实在是太太太莫名其妙了,尤其是封装好的组件,一层套一层的,根本不知道是哪一层出了问题...除了改bug就是做新功能,真想吐槽一下这个项目的留言板,根本没人会用吧...这功能实在是太老旧 ...
- leetcode-三数之和(java)
三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可 ...
- Python入门(1)
一.Python的安装 进入Python官方网站:https://www.python.org/,按照下图操作,下载Python的安装器 下载完成,打开下载好的可执行文件,可以看到如下界面. 然后等待 ...
- Solium代码测试框架
Solium, 在solid中,Linter用于标识和修复样式&安全问题 //调用测试 solium -d contracts --fix 源代码名称:Solium 源代码网址:http:// ...
- 在mesh client示例中加入spi_slave接口(without IDE)
在mesh client示例中加入spi_slave接口(without IDE) 主要是理解cmake构建的过程,然后修改工程中的inlcude路径及c源文件. 1. 解压mesh_sdk unzi ...
- "Hello world!"团队第一次会议
今天是我们"Hello world!"团队第一次召开会议,今天的会议可能没有那么正式,但是我们一起确立了选题——基于WEB的售票系统.博客内容是: 1.会议时间 2.会议成员 3. ...
- 11.22Daily Scrum
人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.979 数据库测试 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.978 实现视频浏览的功能 王 ...