ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AHOI2022 回忆 题解

2022-05-10 00:00:15  阅读:185  来源: 互联网

标签:int 题解 lis back st 回忆 AHOI2022 match out


洛谷:[AHOI2022] 回忆


题解:先鸽着,有时间再写。

时间复杂度:\(O(n\log^2 n)\) 或 \(O(n\log n)\)。

代码:

#include <set>
#include <vector>
#include <cstdio>
#include <algorithm>
const int Maxn=200000;
int n,m;
int head[Maxn+5],arrive[Maxn<<1|5],nxt[Maxn<<1|5],tot;
void add_edge(int from,int to){
	arrive[++tot]=to,nxt[tot]=head[from],head[from]=tot;
}
int s_min[Maxn+5];
int dep[Maxn+5],fa[Maxn+5];
void init_dfs(int u){
	dep[u]=dep[fa[u]]+1;
	for(int i=head[u];i;i=nxt[i]){
		int v=arrive[i];
		if(v==fa[u]){
			continue;
		}
		fa[v]=u;
		init_dfs(v);
	}
}
std::multiset<int> st[Maxn+5];
int match[Maxn+5],out[Maxn+5],putt[Maxn+5];
int num;
void work_dfs(int u){
	match[u]=out[u]=putt[u]=0;
	st[u].clear();
	std::vector<std::pair<int,int> > o_lis;
	for(int i=head[u];i;i=nxt[i]){
		int v=arrive[i];
		if(v==fa[u]){
			continue;
		}
		work_dfs(v);
		match[u]+=match[v];
		while(!st[v].empty()&&*(--st[v].end())>=dep[u]){
			out[v]++,st[v].erase(--st[v].end());
		}
		o_lis.push_back(std::make_pair(out[v],match[v]));
		if(st[u].size()<st[v].size()){
			std::swap(st[u],st[v]);
		}
		for(auto it:st[v]){
			st[u].insert(it);
		}
		st[v].clear();
	}
	if(!o_lis.empty()){
		std::sort(o_lis.begin(),o_lis.end());
		int sum=0;
		for(int i=0;i<(int)o_lis.size()-1;i++){
			sum+=o_lis[i].first+o_lis[i].second*2;
		}
		if(sum>=o_lis.back().first){
			sum=0;
			for(int i=0;i<(int)o_lis.size()-1;i++){
				sum+=o_lis[i].first;
			}
			if(sum>=o_lis.back().first){
				sum+=o_lis.back().first;
				out[u]=sum%2,match[u]+=sum/2;
			}
			else{
				int tmp=o_lis.back().first;
				match[u]+=sum;
				tmp-=sum;
				match[u]+=tmp/2,out[u]=tmp%2;
			}
		}
		else{
			match[u]=sum+o_lis.back().second;
			out[u]=o_lis.back().first-sum;
		}
	}
	if(s_min[u]!=n+1){
		if(st[u].empty()){
			st[u].insert(s_min[u]);
			if(out[u]>0){
				out[u]--,num--;
			}
			else if(match[u]>0){
				match[u]--,out[u]++,num--,putt[u]++;
			}
		}
		else{
			int val=std::min(*st[u].begin(),s_min[u]);
			st[u].erase(st[u].begin());
			st[u].insert(val);
			num--;
		}
	}
}
void solve(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		s_min[i]=n+1,head[i]=0;
	}
	tot=0;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		add_edge(u,v),add_edge(v,u);
	}
	init_dfs(1);
	num=0;
	for(int i=1;i<=m;i++){
		int s,t;
		scanf("%d%d",&s,&t);
		s_min[t]=std::min(s_min[t],dep[s]);
	}
	for(int i=1;i<=n;i++){
		if(s_min[i]!=n+1){
			num++;
		}
	}
	work_dfs(1);
	printf("%d\n",num-match[1]);
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		solve();
	}
	return 0;
}

标签:int,题解,lis,back,st,回忆,AHOI2022,match,out
来源: https://www.cnblogs.com/withhope/p/16251769.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有