「题解报告」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})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
随机推荐
- AcWing-1022
题解借鉴两位大佬的解析 墨染空 && 野生铅笔 本题是一道 01背包 的扩展题 -- 二维费用01背包问题 把 野生宝可梦 看做物品,则捕捉他需要的 精灵球 个数就是第一费用,战斗皮神 ...
- Apache Poi 操作word,替换字符保留样式问题,runs段落混乱问题。
关于这个问题也是刚好遇到,一通搜索也没有找到类似的或者是有效的方法.下面介绍一下. 首先apache poi的引入 <dependency> <groupId>org.apac ...
- 编写一个kubernetes controller
Overview 根据Kuberneter文档对Controller的描述,Controller在kubernetes中是负责协调的组件,根据设计模式可知,controller会不断的你的对象(如Po ...
- SAP 定义用户组
SUGR,可进行创建.查看.删除等维护性操作,并可指定本组的用户
- Quick Pow: 如何快速求幂
今天讲个有趣的算法:如何快速求 \(n^m\),其中 n 和 m 都是整数. 为方便起见,此处假设 m >= 0,对于 m < 0 的情况,求出 \(n^{|m|}\) 后再取倒数即可. ...
- C#中将字符串转换成数值
Convert.ToInt32("999");
- NC16462 [NOIP2015]跳石头
NC16462 [NOIP2015]跳石头 题目 题目描述 一年一度的"跳石头"比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块 ...
- 2018 CSP-J 初赛解析
做题记录与答案 今天这个做的是真的烂,60分,妙极了(微笑 可以看看人家的解析 选择: 选择好多不太懂的,一个个的来解析 先分析一下选择的知识点: 计算机基础 :T1.T3.T4.T5.T8 进制转换 ...
- 【python笔记】Qt+云函数 实现简单的登录框制作
[python笔记]Qt+云函数 实现简单的登录框制作 备注:前置条件:QtDesigner.pycharm.PyQt5.配置好的云函数(百度的叫函数计算CFC,用来充当一个简陋的服务器,主要是免费) ...
- Spring-03
1. AOP相关概念 1.1 AOP概念&作用 AOP(Aspect Oriented Programming)是一种思想,面向切面编程 作用:在不修改源码的前提下,在程序运行过程中对方法进行 ...