首页 > 其他分享 >P10238 [yLCPC2024] F. PANDORA PARADOXXX 题解

P10238 [yLCPC2024] F. PANDORA PARADOXXX 题解

时间:2024-08-16 16:05:16浏览次数:7  
标签:tmp pt P10238 题解 ll 200010 yLCPC2024 son top

题目传送门

前置知识

树链剖分 | 树的直径 | 最近公共祖先 | 并查集

解法

正着删边不太可做,考虑离线下来反着加边。

一个显而易见的结论:设点集 \(A\) 的直径的两个端点为 \(u_{1},v_{1}\),另一个点集 \(B\) 的直径的两个端点为 \(u_{2},v_{2}\),则 \(A \bigcup B\) 的直径端点一定是 \(\{ u_{1},v_{1},u_{2},v_{2} \}\) 中的两个。

并查集维护连通块内直径的两个端点即可。

手动实现下清空来保证复杂度正确。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
ll siz[200010],fa[200010],dep[200010],dis[200010],son[200010],top[200010],u[200010],v[200010],x[200010],vis[200010],ans[200010],tot=0,sum=0;
vector<pair<ll,ll> >e[200010];
void add(ll u,ll v,ll w)
{
	e[u].push_back(make_pair(v,w));
}
void dfs1(ll x,ll father,ll w)
{
	siz[x]=1;
	fa[x]=father;
	dep[x]=dep[father]+1;
	dis[x]=dis[father]+w;
	for(ll i=0;i<e[x].size();i++)
	{
		if(e[x][i].first!=father)
		{
			dfs1(e[x][i].first,x,e[x][i].second);
			siz[x]+=siz[e[x][i].first];
			son[x]=(siz[e[x][i].first]>siz[son[x]])?e[x][i].first:son[x];
		}
	}
}
void dfs2(ll x,ll id)
{
	top[x]=id;
	if(son[x]!=0)
	{
		dfs2(son[x],id);
		for(ll i=0;i<e[x].size();i++)
		{
			if(e[x][i].first!=son[x]&&e[x][i].first!=fa[x])
			{
				dfs2(e[x][i].first,e[x][i].first);
			}
		}
	}
}
ll lca(ll u,ll v)
{
	while(top[u]!=top[v])	
	{
		if(dep[top[u]]>dep[top[v]])
		{
			u=fa[top[u]];
		}
		else
		{
			v=fa[top[v]];
		}
	}
	return (dep[u]<dep[v])?u:v;
}
ll ask_dis(ll x,ll y)
{
	return dis[x]+dis[y]-2*dis[lca(x,y)];
}
struct DSU
{
	ll fa[200010],pt[200010][2],tmp[5];
	void init(ll n)
	{
		for(ll i=1;i<=n;i++)
		{
			fa[i]=i;
			pt[i][0]=pt[i][1]=i;
		}
	}
	ll find(ll x)
	{
		return fa[x]==x?x:fa[x]=find(fa[x]);
	}
	void merge(ll x,ll y)
	{
		if(dep[x]>dep[y])
		{
			swap(x,y);
		}
		x=find(x);
		y=find(y);
		fa[y]=x;
		ll maxx=0;
		tmp[1]=pt[x][0];
		tmp[2]=pt[x][1];
		tmp[3]=pt[y][0];
		tmp[4]=pt[y][1];
		for(ll i=1;i<=4;i++)
		{
			for(ll j=i+1;j<=4;j++)
			{
				if(ask_dis(tmp[i],tmp[j])>maxx)
				{
					maxx=ask_dis(tmp[i],tmp[j]);
					pt[x][0]=tmp[i];
					pt[x][1]=tmp[j];
				}
			}
		}
		sum=max(sum,maxx);
	}
}D;
int main()
{
	ll t,n,q,w,i,j;
	scanf("%lld",&t);
	for(j=1;j<=t;j++)
	{
		scanf("%lld%lld",&n,&q);
		D.init(n);
		tot=sum=0;
		for(i=1;i<=n;i++)
		{
			e[i].clear();
			son[i]=vis[i]=0;
		}
		for(i=1;i<=n-1;i++)
		{
			scanf("%lld%lld%lld",&u[i],&v[i],&w);
			add(u[i],v[i],w);
			add(v[i],u[i],w);
		}
		dfs1(1,0,0);
		dfs2(1,1);
		for(i=1;i<=q;i++)
		{
			scanf("%lld",&x[i]);
			vis[x[i]]=1;
		}
		for(i=1;i<=n-1;i++)
		{
			if(vis[i]==0)
			{	
				D.merge(u[i],v[i]);
			}
		}
		for(i=q;i>=1;i--)
		{
			ans[i]=sum;
			D.merge(u[x[i]],v[x[i]]);	
		}
		for(i=1;i<=q;i++)
		{
			printf("%lld\n",ans[i]);
		}
	}
	return 0;
}

标签:tmp,pt,P10238,题解,ll,200010,yLCPC2024,son,top
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18363057

相关文章

  • 启动应用程序出现pcsvDevice.dll找不到问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个pcsvDevice.dll文件(挑选合适的版本文件)把......
  • P6109 [Ynoi2009] rprmq1 题解
    Description有一个\(n\timesn\)的矩阵\(a\),初始全是\(0\),有\(m\)次修改操作和\(q\)次查询操作,先进行所有修改操作,然后进行所有查询操作。一次修改操作会给出\(l_1,l_2,r_1,r_2,x\),代表把所有满足\(l_1\lei\ler_1\)且\(l_2\lej\ler_2\)的\(a_{i,j}\)元......
  • 题解:P10688 Buy Tickets
    题目大意排队时有人插队。输入格式给定队列长度$n$。接下来$n$行每行两个正整数,第一个表示该元素插入位置,另一个表示该元素的权值。输出格式按照顺序输出该位置元素的权值。注意事项输入的数据组数未知,需要一直输入,输入方法可以参考以下代码。while(cin>>n){......
  • 题解:P10781 【MX-J1-T1】『FLA - III』Spectral
    P10781【MX-J1-T1】『FLA-III』Spectral题解(非正解,正解应该是数学题。)这道题很简单,分析题意就可以得出核心代码:for(inti=1;i<=n;i++){ans=k+ans/i;}那么恭喜你获得$40$pts。为什么呢?因为题目需要的是最高温度,而烧碳获得的温度可能小于烧炭时减低的温度。简单说......
  • JOISC2020 Day 4 A 首都 题解
    JOISC2020Day4A首都JOIAtCoderLuogu考虑一条链的情形。如图,将每个城市视为一条线段,容易发现交错(有交但不包含)的若干线段必须全部合并才能符合条件。但如果这么写会出错,原因是线段有包含关系,外层线段需要统计内层线段的答案,但内层线段不需要统计外层线段的答案。如果设内......
  • 题解:AT_abc365_d [ABC365D] AtCoder Janken 3
    D-AtCoderJanken3题解题意:高桥和青木要玩石头剪刀布,给你一个长度为\(n\)的字符串\(s\),\(s\)表示青木在第\(i\)局游戏中的动作(R表示石头,P表示布,S表示剪刀。)。高桥不可以在任何一局中输给青木(即:高桥和青木只可以平局或高桥赢青木),且高桥第\(i\)局出的和第\(i-1\)局......
  • 题解:P10313 [SHUPC 2024] 占地斗士!
    题目大意给出一个由.和#组成的\(n\timesm\)矩阵,然后再给你这\(4\)种图像,用着四种图像对矩阵进行覆盖(每个只能用一次)。其中,#的位置不可以被图像遮挡,也不能放在不能放置的格子上。解题思路考虑使用爆搜。第一个图像:if(mp[i][j]!='#'&&mp[i+1][j+1]!='#'......
  • 题解:P10111 [GESP202312 七级] 纸牌游戏
    题目大意给出三个序列:\(a\),\(b\),\(c\)分别表示:分数,罚分以及小杨从第\(1\)轮至第\(......
  • 题解:AtCoder Janken 3
    D-AtCoderJanken3题解题意高桥和青木要玩石头剪刀布,给你一个长度为\(n\)的字符串\(s\),\(s\)表示青木在第\(i\)局游戏中的动作(R表示石头,P表示布,S表示剪刀)。高桥不可以在任何一局中输给青木(即:高桥和青木只可以平局或高桥赢青木),且高桥第\(i\)局出的和第\(i-1\)局......
  • Codeforces 232 B Table 题解 [ 蓝 ] [ 分组背包 ] [ 组合数学 ] [ 循环节 ]
    Codeforces232BTable。蒟蒻模拟赛上场切的一道蓝,非常难以置信我竟然能做蓝题。这题的数据范围初看还是比较坑的,\(10^{18}\)的值域很容易让人往矩阵加速那方面想。实际上在列出转移方程式后,我们发现状态是二维的,无法使用矩阵加速(或者说这样做很麻烦)。思路首先观察到每个边长......