题解

显然权值都是正的,我们最深的那个点一定延伸到了某个叶子

我们抛去这条链之外再选K个点即可

如果直接对一棵树选K个点,满足这样的依赖关系,可以通过一个后序遍历的顺序做出来

转移方法是

\(dp[i][j] = dp[i - 1][k] + (j - k) * v\)

或者

\(dp[i][j] = dp[i - siz[u]][j]\)

代表这个点选或者不选

我们把每个点拆成1和a[i] - 1两个点,然后做两次儿子遍历顺序恰好相反的dp

我们枚举一个叶子的时候,在这个点右侧这两个后序遍历重合的地方只有这个叶子到根所有点,这也是我们要必选的点

然后我们用两个遍历中这个点左侧的点集,枚举每个点集选几个,来更新答案即可

代码

#include <bits/stdc++.h>
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define MAXN 40005
//#define ivorysi
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
} template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
struct node {
int to,next;
}E[MAXN * 2];
int64 tot;
int N,K,head[MAXN],sumE,fa[MAXN],Ncnt,v[MAXN],a[MAXN],sumv[MAXN];
int siz[MAXN],dep[MAXN],LA[MAXN],posA[MAXN],LB[MAXN],posB[MAXN],idx;
int f[51000005],g[51000005],Q1[500005],Q2[500005],ql,qr;
bool lef[MAXN];
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
void dfsa(int u) {
siz[u] = 1;dep[u] = dep[fa[u]] + 1;sumv[u] = sumv[fa[u]] + v[u];
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
dfsa(v);siz[u] += siz[v];
}
LA[++idx] = u;posA[u] = idx;
}
void dfsb(int u) {
vector<int> son;son.clear();
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;son.pb(v);
}
reverse(son.begin(),son.end());
for(int i = 0 ; i < son.size() ; ++i) dfsb(son[i]);
LB[++idx] = u;posB[u] = idx;
}
void DP(int *L,int *p,int *f) {
for(int i = 1 ; i <= Ncnt ; ++i) {
int u = L[i];
int *f1 = f + (i - 1) * (K + 1),*f2 = f + i * (K + 1);
memcpy(f2,f + (p[u] - siz[u]) * (K + 1),sizeof(int) * (K + 1));
if(u <= N) {
for(int j = 1 ; j <= K ; ++j) f2[j] = max(f2[j],f1[j - 1] + v[u]);
}
else {
Q1[ql = qr = 1] = 0;Q2[1] = 0;
for(int j = 1 ; j <= K ; ++j) {
while(ql <= qr && j - Q1[ql] > a[u]) ++ql;
if(ql <= qr) f2[j] = max(f2[j],Q2[ql] + j * v[u]);
while(ql <= qr && f1[j] - j * v[u] >= Q2[qr]) --qr;
Q2[++qr] = f1[j] - j * v[u];Q1[qr] = j;
}
}
}
}
void Init() {
memset(head,0,sizeof(head));
memset(lef,0,sizeof(lef));
sumE = 0;tot = 0;
memset(f,0,sizeof(int) * Ncnt * (K + 1));
memset(g,0,sizeof(int) * Ncnt * (K + 1));
read(N);read(K);
Ncnt = N;
for(int i = 1 ; i <= N ; ++i) {
read(fa[i]);read(a[i]);read(v[i]);
if(fa[i] != 0) add(fa[i],i);
lef[fa[i]] = 1;
tot += a[i];
if(a[i] > 1) {
add(i,++Ncnt);fa[Ncnt] = i;v[Ncnt] = v[i];a[Ncnt] = a[i] - 1;a[i] = 1;
}
}
idx = 0;dfsa(1);
idx = 0;dfsb(1);
}
void Solve() {
DP(LA,posA,f);
DP(LB,posB,g);
int ans = 0;
for(int u = 1 ; u <= N ; ++u) {
if(!lef[u]) {
int *df = f + (K + 1) * (posA[u] - 1),*dg = g + (K + 1) * (posB[u] - siz[u]);
int64 cur = min((int64)K,tot - dep[u]);
for(int j = 0 ; j <= cur ; ++j) {
ans = max(ans,df[j] + dg[cur - j] + sumv[u]);
}
}
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T;
read(T);
while(T--) {
Init();
Solve();
}
return 0;
}

感觉一看到SDOI R2自动降智

这么难的省选题要是我去考根本考不动啊

【LOJ】#2268. 「SDOI2017」苹果树的更多相关文章

  1. loj#2269. 「SDOI2017」切树游戏

    还是loj的机子快啊... 普通的DP不难想到,设F[i][zt]为带上根玩出zt的方案数,G[i][zt]为子树中的方案数,后面是可以用FWT优化的 主要是复习了下动态DP #include< ...

  2. loj#2002. 「SDOI2017」序列计数(dp 矩阵乘法)

    题意 题目链接 Sol 质数的限制并没有什么卵用,直接容斥一下:答案 = 忽略质数总的方案 - 没有质数的方案 那么直接dp,设\(f[i][j]\)表示到第i个位置,当前和为j的方案数 \(f[i ...

  3. @loj - 2004@ 「SDOI2017」硬币游戏

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数 ...

  4. LOJ #2005. 「SDOI2017」相关分析 线段树维护回归直线方程

    题目描述 \(Frank\) 对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. \(Frank\) 不仅喜欢观测,还喜欢分析观测到的 ...

  5. LibreOJ 2003. 「SDOI2017」新生舞会 基础01分数规划 最大权匹配

    #2003. 「SDOI2017」新生舞会 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. HGOI 20181027 幻象(概率DP)

    40 pts: 考场上打了40分暴力,理论的话就是概率树,把每一个状态去去到各个带权(概率)的和就是答案 最终处理的话就是dfs出01序列0代表没有幻象,1代表出现幻象然后在每一次dfs出一段序列的时 ...

  2. 【转】Keil ARM开发 error L6236E错误解决

    顺利创建了第一个Keil工程却发现不能完成链接,出现了一个下面这样的报错: .\Objects\demo_simple.sct(7): error: L6236E: No section matche ...

  3. 解决360WiFi有时候手机连接不上

    有可能是无线网卡的问题: 右击“计算机”->选择“管理”->“设备管理器”->网络适配器->选择“Broadcom  802.11n 网络适配器”,或者你实在不知道哪个是无线网 ...

  4. 洛谷P1280 尼克的任务

    这个DP气死我了.....写的时候脑子比较迟钝于是爆0了好几次,最后还是我旁边的AKIOI巨佬告诉我解法才会做. 我一开始设计的状态是f[i]表示i时刻正在休息,从1到i的最长休息时间. 然后经历了各 ...

  5. 【CF61D】Eternal Victory

    题目大意:给定一棵 N 个节点的树,求从 1 号节点(根节点)出发,任意节点结束,且至少经过每个节点一次的最短路径是多少. 题解:首先考虑最终要回到根节点的情况,可以发现最短路径长度一定等于该树边权的 ...

  6. 使用Arraylist将数组中元素随机均等乱序分为N个子数组

    使用Arraylist将数组中元素随机均等乱序分为N个子数组 觉得有用的话,欢迎一起讨论相互学习~Follow Me 为了将数组中的元素 随机地 ,均等地, 不重复地 ,划分到N个子数组中 使用Arr ...

  7. python获取指定目录下所有文件名os.walk和os.listdir

    python获取指定目录下所有文件名os.walk和os.listdir 觉得有用的话,欢迎一起讨论相互学习~Follow Me os.walk 返回指定路径下所有文件和子文件夹中所有文件列表 其中文 ...

  8. python---django中orm的使用(2)

    1.基于对象的正向查询和反向查询 在python---django中orm的使用(1)中也提到了正向和反向查找 表:一对多  书籍和出版社 class Book(models.Model): titl ...

  9. (一)Git时间--初识版本控制工具

    //配置一下你的身份 git config --global use.name "Douzi" git config --global use.email "jdouzi ...

  10. Mahalanobis距离(马氏距离)的“哲学”解释

    讲解教授:赵辉 (FROM : UESTC) 课程:<模式识别> 整理:PO主 基础知识: 假设空间中两点x,y,定义: 欧几里得距离, Mahalanobis距离, 不难发现,如果去掉马 ...