码迷,mamicode.com
首页 > 其他好文 > 详细

【重链剖分】The 15-th Beihang University Collegiate Programming Contest (BCPC 2020) - Final H、宝可梦与分支进化

时间:2021-05-24 14:49:30      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:turn   while   for   targe   ack   The   AMM   ==   hang   

题链

dp[x] 表示以 x 为进化终点能取得的最大进化次数;

可以发现 dp[x] 等于 树上x的前缀最大值 +1;

但是不可能递归寻找x的父亲直到根节点,因为会超时;

所以采用重链剖分+线段树维护前缀最大值,复杂度O(nlogn*logn);

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ll long long
#define ULL unsigned long long
#define Pair pair<LL,LL>
#define ls rt<<1
#define rs rt<<1|1
#define Pi acos(-1.0)
#define eps 1e-6
#define DBINF 1e100
#define mod 998244353
#define MAXN 1e18
#define MS 500009

int n,m;
vector<int > vc[MS];
int fa[MS];
int sz[MS];
int dep[MS];
int zson[MS];
int tim;
int top[MS];
int dfn[MS];
int val[MS];
int p[MS<<2];

void dfs1(int u,int f){
	fa[u] = f;
	sz[u] = 1;
	dep[u] = dep[f]+1;
	zson[u] = 0;
	int maxn_zson = 0;
	for(auto &v:vc[u]){
		if(v == f) continue;
		dfs1(v,u);
		sz[u] += sz[v];
		if(sz[v] > maxn_zson){
			zson[u] = v;
			maxn_zson = sz[v];
		}
	}
} 

void dfs2(int u,int tp){
	dfn[u] = ++tim;
	top[u] = tp;
	val[tim] = 0;
	if(zson[u]) dfs2(zson[u],tp);
	for(auto &v:vc[u]){
		if(v == fa[u] || v == zson[u]) continue;
		dfs2(v,v);
	}
}

void update(int pos,int l,int r,int rt,int val){
	if(l == r){
		p[rt] = val;
		return;
	}
	int m = l+r>>1;
	if(m >= pos) update(pos,l,m,ls,val);
	if(m <  pos) update(pos,m+1,r,rs,val);
	p[rt] = max(p[ls],p[rs]);
}

int query(int L,int R,int l,int r,int rt){
	if(L <= l && r <= R){
		return p[rt];
	}
	int ans = 0;
	int m = l+r>>1;
	if(m >= L) ans = max(ans,query(L,R,l,m,ls));
	if(m <  R) ans = max(ans,query(L,R,m+1,r,rs));
	return ans;
}

int get_max(int x){
	if(x == fa[x]) return 0; // 如果是根节点则无前缀,返回 0 
	x = fa[x]; // 从x的父亲为起点,向上跳 
	int ans = query(dfn[x],dfn[x],1,n,1); // 初值为父亲的值 
	while(x != fa[x]){ // 一直跳到根节点 
		ans = max(ans, query(dfn[top[x]],dfn[x],1,n,1) );
		x = fa[top[x]];
	}
	return ans;
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=2;i<=n;i++){
		int x;
		cin >> x;
		vc[x].push_back(i);
	}
	dfs1(1,1);
	dfs2(1,1);
	int ans = 0;
	for(int i=1;i<=m;i++){
		int x;
		cin >> x;
		int cc = get_max(x)+1; // 求 x 的前缀最大值(不含 x ) 
		update(dfn[x],1,n,1,cc);
		ans = max(ans,cc);
	}
	cout << ans << "\n";
	
	
	return 0;
}

【重链剖分】The 15-th Beihang University Collegiate Programming Contest (BCPC 2020) - Final H、宝可梦与分支进化

标签:turn   while   for   targe   ack   The   AMM   ==   hang   

原文地址:https://www.cnblogs.com/Tecode/p/14780985.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!