[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\)权值,所以成对的权值可以分到每个点上 所以每个非叶节点实际对应一个 ...
随机推荐
- dubbo入门(一)
1.简介 Dubbo由阿里巴巴开源,是一个分布式服务框架,致力于提供高性能和透明化的RPC(远程过程调用)远程服务调用方案,以及SOA服务治理方案.如果没有分布式的需求,Dbubbo是不需要的,其本质 ...
- 成员变量:对象vs指针
一旦类初始化,那么对象必然会被创建,指针则可以在需要时候再去初始化所指向.
- Java小记(1)
return 关键字 package mytest; public class Test4 { public static void main(String[] args) { // TODO Aut ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述
第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...
- HDU-1496(哈希表)
Hash入门第一题 题意: 问题描述 考虑具有以下形式的方程: a * x1 ^ 2 + b * x2 ^ 2 + c * x3 ^ 2 + d * x4 ^ 2 = 0 a,b,c,d是来自区间[- ...
- lintcode 二分查找
题目:二分查找 描述:给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1. c ...
- [转载]Java集合框架的常见面试题
http://www.jfox.info/40-ge-java-ji-he-lei-mian-shi-ti-he-da-an 整理自上面链接: Java集合框架为Java编程语言的基础,也是Java面 ...
- 接口_requests_基于python
HTTP request python官方文档:http://cn.python-requests.org/zh_CN/latest/ 1. 环境 基于环境,需要安装requests 模块,安装方法 ...
- css修改placeholder的样式
css修改placeholder的样式 input::-webkit-input-placeholder { /* WebKit browsers */ font-size:14px; color: ...
- js经典试题之常用的方法
js经典试题之常用的方法 1.下面代码输出的值 let s = "bob" const replaced = s.replace('b', 'l') replaced === &q ...