[省选联考 2021]宝石

宝石

题解

很水的一道题

首先可以考虑将询问 ( s , t ) (s,t) (s,t)拆成 ( s , l c a ( s , t ) ) (s,lca(s,t)) (s,lca(s,t)) ( l c a ( s , t ) , t ) (lca(s,t),t) (lca(s,t),t)两部分,离线下来处理。
由于在序列 P P P中,每种颜色都是唯一的,所以每个节点能在答案序列中所处的位置也是唯一的。
我们可以先用倍增的方式更新出来点 s s s在序列中向前/向后走多少步时能够到达哪个节点。
但由于开始开始节点不一定是节点 s s s,所以我们要离线下来记录下距当前点最近的某种颜色的点的位置,就像序列自动机那样,当然只需要存储当前这个点的状态了。
然后我们可以二分从这个点可以向上走多少步不超过lca,其实可以不用二分的,直接从高位开始枚举的

然后我们接着处理 ( l c a ( s , t ) , t ) (lca(s,t),t) (lca(s,t),t)的部分,我们既然已经知道了前一部分的答案,我们可以二分着个部分的答案,再判断点 t t t从答案开始,能否走完这部分新加的部分且不超过lca
这样就可以 O ( l o g 2 n ) O\left(log^2n\right) O(log2n)解决这两个部分了。

总时间复杂度 O ( n l o g 2 n ) O\left(nlog^2n\right) O(nlog2n)

题解

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<time.h>
using namespace std;
#define MAXN 200005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
typedef unsigned int uint;
typedef pair<int,int> pii;
const int INF=0x7f7f7f7f;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int n,q,m,c,head[MAXN],tot,P[MAXN],col[MAXN],ltp[MAXN],dep[MAXN],L[MAXN],R[MAXN];
int father[MAXN],dfn[MAXN],pre[MAXN],idx,wson[MAXN],siz[MAXN],sta[MAXN],stak;
int pcol[MAXN][22],ncol[MAXN][22],icol[MAXN],hcol[MAXN],ans[MAXN];
vector<int>F[MAXN],T[MAXN];
struct edge{int to,nxt;}e[MAXN<<1];
struct ask{int s,t;}s[MAXN];
void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
void dosaka1(int u,int fa){
	siz[u]=1;father[u]=fa;wson[u]=0;dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa)continue;
		dosaka1(v,u);siz[u]+=siz[v];
		if(siz[wson[u]]<siz[v])wson[u]=v;
	}
}
void dosaka2(int u,int tp){
	dfn[u]=++idx;ltp[u]=tp;pre[idx]=u;int las=hcol[col[u]];hcol[col[u]]=u;
	pcol[u][0]=hcol[P[icol[col[u]]-1]];ncol[u][0]=hcol[P[icol[col[u]]+1]];
	for(int i=1;i<21;i++)pcol[u][i]=pcol[pcol[u][i-1]][i-1],ncol[u][i]=ncol[ncol[u][i-1]][i-1];
	if(wson[u])dosaka2(wson[u],tp);
	for(int i=head[u];i;i=e[i].nxt)
		if(e[i].to!=wson[u]&&e[i].to!=father[u])
			dosaka2(e[i].to,e[i].to);
	hcol[col[u]]=las;
}
int lca(int a,int b){
	while(ltp[a]^ltp[b]){
		if(dep[ltp[a]]<dep[ltp[b]])swap(a,b);
		a=father[ltp[a]];
	}
	return dep[a]<dep[b]?a:b;
}
int FindPre(int u,int dp){for(int i=20;i>=0;i--)if(dp>>i&1)u=pcol[u][i];return u;}
int FindNxt(int u,int dp){for(int i=20;i>=0;i--)if(dp>>i&1)u=ncol[u][i];return u;}
void dosaka3(int u,int fa){
	int las=hcol[col[u]],siz=F[u].size();hcol[col[u]]=u;
	for(int i=0;i<siz;i++){
		int ti=F[u][i],v=s[ti].t,u_v=lca(u,v);int l=0,r=c;if(dep[hcol[P[1]]]<dep[u_v])continue; 
		while(l<r){int mid=l+r+1>>1;if(dep[u_v]>dep[FindNxt(hcol[P[1]],mid)])r=mid-1;else l=mid;}ans[ti]=l+1;
	}
	for(int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa)dosaka3(e[i].to,u);hcol[col[u]]=las;
}
void dosaka4(int u,int fa){
	int las=hcol[col[u]],siz=T[u].size();hcol[col[u]]=u;
	for(int i=0;i<siz;i++){
		int ti=T[u][i],v=s[ti].s,u_v=lca(u,v);int l=0,r=c-ans[ti];if(dep[hcol[P[ans[ti]+1]]]<dep[u_v])continue;
		while(l<r){int mid=l+r+1>>1;if(dep[u_v]>dep[FindPre(hcol[P[ans[ti]+mid+1]],mid)])r=mid-1;else l=mid;}ans[ti]+=l+1;
	}
	for(int i=head[u];i;i=e[i].nxt)if(e[i].to!=fa)dosaka4(e[i].to,u);hcol[col[u]]=las;
}
signed main(){
	read(n);read(m);read(c);
	for(int i=1;i<=c;i++)read(P[i]),icol[P[i]]=i;
	for(int i=1;i<=n;i++)read(col[i]);
	for(int i=1,u,v;i<n;i++)read(u),read(v),addEdge(u,v),addEdge(v,u);
	dosaka1(1,0);dosaka2(1,1);read(q);
	for(int i=1;i<=q;i++)read(s[i].s),read(s[i].t),F[s[i].s].push_back(i),T[s[i].t].push_back(i);
	dosaka3(1,0);dosaka4(1,0);for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
	return 0;
}

谢谢!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\],取证2022七省联考的考生将获得中国PostgreSQL分会颁发的《中国PostgreSQL认证考试技术能力证书》和工信部下属中国电子工业标准化协会颁发的《中国电子信息行业专业技术认定证书》两份证书。这两份证书具有较高的认可度和应用价值,可以在招投标、求职、职称晋升、抵税等方面发挥作用。此外,取证学员还可以享受全职业周期、全国覆盖的就业推荐服务。\[1\] 关于直径的计算,根据引用\[2\]和引用\[3\],在树的分裂情况下,最后的直径的长度可能是以下三种情况的最大值: 1. tree1的直径,假设tree1中,原来最长链的一段为root1。 2. tree2的直径,假设tree2中,原来最长链的一段为root2。 3. tree1的某一个点和tree2的某一个点连接的最长链。 在情况3中,最优的连线方式是取tree1直径的一半、tree2直径的一半并连线。如果直径是奇数,则需要向上取整。具体表达为:⌈Max1\[u\]/2⌉ + ⌈Max2\[v\]/2⌉ + 1。\[3\] 综上所述,取证2022七省联考的考生将获得两份证书,并且在计算直径时需要考虑三种情况,其中情况3的最优连线方式是取tree1直径的一半、tree2直径的一半并连线,如果直径是奇数,则需要向上取整。 #### 引用[.reference_title] - *1* [全国联考 | PostgreSQL初、中级认证考试(5.22)通过考生公示](https://blog.csdn.net/weixin_46199817/article/details/117329421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [『树直径·树形DP』「四校联考」平衡树](https://blog.csdn.net/Ronaldo7_ZYB/article/details/90488429)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值