【CF1528C】Trees of Tranquillity


題目

題目鏈接:https://codeforces.com/problemset/problem/1528/C
給定兩棵大小為 \(n\) 的樹,以及 \(n\) 個點,點 \(x,y\) 之間會有連邊當且僅當 \(x,y\) 在第一棵樹上為祖孫關系,且在第二棵樹上不是祖孫關系。
求圖的最大團。多測。
\(Q,\sum n\leq 3\times 10^5\)

思路

oisdoaiu CCCCCCCCOrz。
等價於在第一棵樹上 \(1\)\(x\) 的一條鏈上的所有點,選盡量多滿足它們在第二棵樹上的子樹不交。
在第一棵樹上 dfs,當搜索到點 \(x\) 的時候,如果選出的祖先中有一個與 \(x\) 的子樹有交集,肯定選擇孫子最優。
又因為題目保證每一個節點的父親編號比他小,所以等價於肯定選 \(x\)
那么我們需要實現的就是區間覆蓋,單點查詢,直接用樹狀數組維護即可。
時間復雜度 \(O(n\log n)\)

代碼

#include <bits/stdc++.h>
using namespace std;

const int N=300010;
int Q,n,tot,ans,cnt,head[N],a[N],b[N],id[N],siz[N];

struct edge
{
	int next,to;
}e[N];

void add(int from,int to)
{
	e[++tot]=(edge){head[from],to};
	head[from]=tot;
}

struct BIT
{
	int c[N];
	
	void add(int x,int v)
	{
		for (int i=x;i<=n;i+=i&-i)
			c[i]+=v;
	}
	
	int query(int x)
	{
		int ans=0;
		for (int i=x;i;i-=i&-i)
			ans+=c[i];
		return ans;
	}
}bit;

void prework()
{
	tot=ans=cnt=0;
	for (int i=1;i<=n;i++)
		head[i]=-1,bit.c[i]=0;
}

void dfs1(int x)
{
	id[x]=++tot; siz[x]=1;
	for (int i=head[x];~i;i=e[i].next)
		dfs1(e[i].to),siz[x]+=siz[e[i].to];
}

void dfs2(int x)
{
	int y=bit.query(id[x]);
	if (y) bit.add(id[y],-y),bit.add(id[y]+siz[y],y);
		else cnt++,ans=max(ans,cnt);
	bit.add(id[x],x); bit.add(id[x]+siz[x],-x);
	for (int i=head[x];~i;i=e[i].next)
		dfs2(e[i].to);
	bit.add(id[x],-x); bit.add(id[x]+siz[x],x);
	if (y) bit.add(id[y],y),bit.add(id[y]+siz[y],-y);
		else cnt--;
}

void work()
{
	scanf("%d",&n);
	for (int i=2;i<=n;i++) scanf("%d",&a[i]);
	for (int i=2;i<=n;i++) scanf("%d",&b[i]);
	prework();
	for (int i=2;i<=n;i++) add(b[i],i);
	tot=0; dfs1(1);
	prework();
	for (int i=2;i<=n;i++) add(a[i],i);
	dfs2(1);
	printf("%d\n",ans);
}

int main()
{
	scanf("%d",&Q);
	while (Q--) work();
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM