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