专栏文章

题解:AT_abc246_g [ABC246G] Game on Tree 3

AT_abc246_g题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min2l7ic
此快照首次捕获于
2025/12/01 19:32
3 个月前
此快照最后确认于
2025/12/01 19:32
3 个月前
查看原文
简单题。
按照结果的 AA 从大到小顺序考虑。对于 AA 的最大值,青木若想结果比它小,那么至少在到达写有该 AA 的节点的父亲时,需要选择把它变成 00。继续递推着,在处理完前面的限制后,发现当前 AA 带来的限制可以表示为,在目前写有该 AA 的节点的未被选用的祖先中,需选择一个,在到达它时,青木选择这个节点。否则可以逆推出高桥可以得到该 AA。当然,可以贪心地推得,最优时选的是深度最大的那一个。那么这样就可以使用并查集维护了,当找不到满足条件的祖先来选择时,答案自然就无法比它更小。
鲜花:出成联赛模拟 T2,O(nlogn)O(n\log n) 给 80 部分,把数据范围调成只放 O(nα(n))O(n \alpha (n)) 过,想来还是相当有杀伤力的。
CPP
#include <bits/stdc++.h>
using namespace std;

inline int rd(){
	char c = getchar();
	while((c > '9' || c < '0') && c != '-') c = getchar();
	int ret = 0; 
	while(c >= '0' && c <= '9') ret = (ret << 3) + (ret << 1) + c - '0', c = getchar();
	return ret;
}

int n;
int father[200002];
vector<int> vec[200002];
void init(int pos,int faa){
	father[pos] = faa;
	for(int i=0;i<vec[pos].size();i++){
		if(vec[pos][i] == faa) continue;
		init(vec[pos][i], pos);
	}
}
pair<int,int> Data[200002];
int fa[200002], cnt[200002], node[2000002];
int getfa(int u){
	if(fa[u] == u) return u;
	fa[u] = getfa(fa[u]);
	return fa[u];
}

int main(){
	
	n = rd();
	for(register int i=1;i<=n;i++) fa[i] = i, cnt[i] = 1, node[i] = i;
	for(register int i=1;i<=n-1;i++){
		scanf("%d",&Data[i].first);
		Data[i].second = i + 1;
	}
	for(int i=1;i<n;i++){
		int u, v;
		scanf("%d%d",&u,&v);
		vec[u].push_back(v);
		vec[v].push_back(u);
	}
	sort(Data+1,Data+n);
	init(1, 0); 
	
	register int i;
	
	for(i=n-1;i>=1;i--){
		int u = getfa(father[Data[i].second]);
		if(node[u] == 0) break;
		if(node[u] == 1) {
			node[u] = 0;
			continue;
		}
		int v = getfa(father[node[u]]);
		int then = node[v];
		if(cnt[u] > cnt[v]) swap(u, v);
		cnt[v] += cnt[u], fa[u] = v;
		node[v] = then;
	}
	printf("%d",Data[i].first);
	
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...