「题解报告」P4577 [FJOI2018]领导集团问题
题解 P4577 [FJOI2018]领导集团问题
题解区好像没有线段树上又套了二分的做法,于是就有了这片题解。
怀着必 WA 的决心交了两发,一不小心就过了。
题意
求一个树上最长不下降子序列。
思路
首先考虑裸的 dp:设 \(f_{u,j}\) 表示以 \(u\) 为根的子树里选的数的最大值不小于 \(j\) 能选多少个。
\begin{cases}
\sum_\limits{v\ is\ u's\ son}f_{v,j} &j>w_u\\
\max\{\sum_\limits{v\ is\ u's\ son}f_{v,j},\sum_\limits{v\ is\ u's\ son}f_{v,j+1}+1\} &j\le w_u
\end{cases}
\]
接下来是如何优化:
在 DFS 每个节点的过程中,用权值线段树维护 \(f_{u,j}\)。
首先把所有儿子的权值线段树和起来。
然后考虑在什么区间选上这个节点更优。
右端点肯定是 \(w_i\) ,那么我们二分求左端点,即二分一个最小的选了比不选更优的点。
单点查询用权值线段树,合并儿子们的树用线段树合并,区间修改用标记可持久化。
时间复杂度是 \(O(nlog^2n)\)。
虽然慢到起飞但是能过。
代码
#include<bits/stdc++.h>
#define _for(i,a,b) for(int i=a;i<=b;++i)
#define for_(i,a,b) for(int i=a;i>=b;--i)
#define ll long long
#define bdmd int mid=(l+r)>>1
using namespace std;
const int N=2e5+10,inf=0x3f3f3f3f;
int n,cnt,w[N];
vector<int>son[N];
inline int rnt(){
int x=0,w=1;char c=getchar();
while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*w;
}
namespace LISAN{
int ls[N];
void LiSan(){
_for(i,1,n){
ls[i]=w[i];
}
sort(ls+1,ls+n+1);
cnt=unique(ls+1,ls+n+1)-ls-1;
_for(i,1,n)
w[i]=lower_bound(ls+1,ls+cnt+1,w[i])-ls;
return;
}
}
class ValSegmentTree{
public:
int root[N],tot,uucnt,un_use[N*40];
class TREE{
public:
int left_son,right_son;
int val=0;
}tree[N*40];
const TREE NONE=(TREE){0,0,0};
#define ls(p) tree[p].left_son
#define rs(p) tree[p].right_son
#define l_s(p) tree[p].left_son,l,mid
#define r_s(p) tree[p].right_son,mid+1,r
#define va(p) tree[p].val
#define bdmd int mid=(l+r)>>1
inline int NewP(){
if(uucnt)
return un_use[uucnt--];
return ++tot;
}
inline void DeleteP(int p){
tree[p]=NONE;
un_use[++uucnt]=p;
return;
}
void UpdateQJ(int &p,int l,int r,int le,int ri,int val){
if(!p)p=NewP();
if(ri<l||r<le)return;
if(le<=l&&r<=ri)
va(p)+=val;
else{
bdmd;
UpdateQJ(l_s(p),le,ri,val);
UpdateQJ(r_s(p),le,ri,val);
}
}
int QueryP(int p,int l,int r,int x){
if(!p)return 0;
if(l==r)return va(p);
else{
bdmd;
if(x<=mid)
return va(p)+QueryP(l_s(p),x);
else
return va(p)+QueryP(r_s(p),x);
}
}
void Merge(int &p1,int p2){
if(!p1){p1=p2;return;}
if(!p2){return;}
va(p1)+=va(p2);
Merge(ls(p1),ls(p2));
Merge(rs(p1),rs(p2));
DeleteP(p2);
return;
}
#undef ls
#undef rs
#undef l_s
#undef r_s
#undef va
}tr;
void Dfs(int u,int father){
int sz=son[u].size();
_for(i,0,sz-1){
int v=son[u][i];
if(v==father)continue;
Dfs(v,u);
tr.Merge(tr.root[u],tr.root[v]);
}
int xuan=tr.QueryP(tr.root[u],1,cnt,w[u]+1)+1;
int l=1,r=w[u];
while(l<=r){
bdmd;
if(tr.QueryP(tr.root[u],1,cnt,mid)>=xuan)
l=mid+1;
else
r=mid-1;
}
tr.UpdateQJ(tr.root[u],1,cnt,l,w[u],1);
return;
}
int main(){
n=rnt();
_for(i,1,n)w[i]=rnt();
LISAN::LiSan();
_for(i,2,n){
int x=rnt();
son[i].push_back(x);
son[x].push_back(i);
}
Dfs(1,0);
printf("%d\n",tr.QueryP(tr.root[1],1,n,1));
return 0;
}
「题解报告」P4577 [FJOI2018]领导集团问题的更多相关文章
- P4577 [FJOI2018]领导集团问题
P4577 [FJOI2018]领导集团问题 我们对整棵树进行dfs遍历,并用一个multiset维护对于每个点,它的子树可取的最大点集. 我们遍历到点$u$时: 不选点$u$,显然答案就为它的所有子 ...
- 「题解报告」 P3167 [CQOI2014]通配符匹配
「题解报告」 P3167 [CQOI2014]通配符匹配 思路 *和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配. 我们首先把原字符串分成多个以一个通 ...
- 「题解报告」P2154 虔诚的墓主人
P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...
- 「题解报告」SP16185 Mining your own business
题解 SP16185 Mining your own business 原题传送门 题意 给你一个无向图,求至少安装多少个太平井,才能使不管那个点封闭,其他点都可以与有太平井的点联通. 题解 其他题解 ...
- 「题解报告」Blocks
P3503 Blocks 题解 原题传送门 思路 首先我们可以发现,若 \(a_l\) ~ \(a_r\) 的平均值大于等于 \(k\) ,则这个区间一定可以转化为都大于等于 \(k\) 的.我们就把 ...
- 「题解报告」P3354
P3354 题解 题目传送门 一道很恶心的树形dp 但是我喜欢 题目大意: 一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄.建了伐木场的村庄可以直接处理木料,否则要往下游的伐木 ...
- 「题解报告」CF1067A Array Without Local Maximums
大佬们的题解都太深奥了,直接把转移方程放出来让其他大佬们感性理解,蒟蒻们很难理解,所以我就写了一篇让像我一样的蒟蒻能看懂的题解 原题传送门 动态规划三部曲:确定状态,转移方程,初始状态和答案. --神 ...
- 洛谷P4577 [FJOI2018]领导集团问题(dp 线段树合并)
题意 题目链接 Sol 首先不难想到一个dp,设\(f[i][j]\)表示\(i\)的子树内选择的最小值至少为\(j\)的最大个数 转移的时候维护一个后缀\(mx\)然后直接加 因为后缀max是单调不 ...
- 「题解报告」P7301 【[USACO21JAN] Spaced Out S】
原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
随机推荐
- 2.shell脚本99乘法表
shell脚本99乘法表 [root@localhost data]# vim cf.sh
- 『忘了再学』Shell流程控制 — 34、if条件判断语句(二)
目录 1.多分支if条件语句格式 2.练习 3.说明 4.综合练习 1.多分支if条件语句格式 if [ 条件判断式1 ] then 当条件判断式1成立时,执行程序1 elif [ 条件判断式2 ] ...
- Volcano成Spark默认batch调度器
摘要:对于Spark用户而言,借助Volcano提供的批量调度.细粒度资源管理等功能,可以更便捷的从Hadoop迁移到Kubernetes,同时大幅提升大规模数据分析业务的性能. 2022年6月16日 ...
- Vue 安装 vue的基本使用 vue的初步使用步骤
1. 资源: https://cn.vuejs.org/v2/guide/#%E8%B5%B7%E6%AD%A5 进入官网学习 2. 点击安装,要把vue下载到本地文件的根目录中,不要选择压缩版的,这 ...
- 分享|智慧环保-生态文明信息化解决方案(附PDF)
内容摘要: 生态文明建设被提到前所未有的战略高度,我们既要绿水青山,也要金山银山.宁要绿水青山,不要金山银山,而且绿水青山就是金山银山.要正确处理好经济发展同生态环境保护的关系,牢固树立保护生态环境就 ...
- Git代码提交报错 (Your branch is up to date with 'origin/master)
一.前言 今天码云上提交自己本地的一个SpringBoot+Vue的小项目,由于前端代码提交第一次时候提交码云上文件夹下为空,于是自己将本地代码复制到码云拉取下来代码文件夹下,然而git add . ...
- 一次 Keepalived 高可用的事故,让我重学了一遍它!
原文首发: 你好,我是悟空. 前言 上次我们遇到了一个 MySQL 故障的事故,这次我又遇到了另外一个奇葩的问题: Keepalived 高可用组件的虚拟 IP 持续漂移,导致 MySQL 主从不断切 ...
- nginx转发rabbitmq
第一种: 直接加个location块 location /rabbitmq/ { proxy_pass http://127.0.0.1:15672/; } 第二种: location /rabbit ...
- windows10 安装MySQL ZIP版本
今天重新学习了一下MySQL,但是呢刷题网站不知道为什么很卡,输入容易卡死崩溃,于是乎想在win10上面进行安装进行练习. 发现电脑里面没有,于是进行安装. 1.首先下载MySQL https://d ...
- NC15553 数学考试
NC15553 数学考试 题目 题目描述 今天qwb要参加一个数学考试,这套试卷一共有 \(n\) 道题,每道题qwb能获得的分数为 \(a_i\) ,qwb并不打算把这些题全做完, 他想选总共 \( ...