xay loves trees(主席树dfs序 标记永久化优化)

Posted 爷灬傲奈我何123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xay loves trees(主席树dfs序 标记永久化优化)相关的知识,希望对你有一定的参考价值。

链接

题意:

思路:早上更新那题的强化版。用线段树尺取,或者主席树,主席树维护从根节点到链上的最大深度。每次插入新节点,询问不符合节点的id,由于区间不相交,这样的值最多一个。 每次更新一下答案就可以了。

// Problem: xay loves trees
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11258/F
// Memory Limit: 1048576 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//#pragma GCC target("avx")
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast")
// created by myq 
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;
const int N = 400010;
const int mod=998244353;
inline int read()
{
	int res=0;
	int f=1;
	char c=getchar();
	while(c>'9' ||c<'0')
	{
		if(c=='-')	f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		res=(res<<3)+(res<<1)+c-'0';
		c=getchar(); 
	}
	return res;
 } 
const int maxn=300010;
 struct node{
 	int l;
 	int r;
 	int mx;
 	int lz;
 }tr[maxn*32];
 vector<int>v[maxn],g[maxn];
 int cnt;
 int n;
 int dep[maxn];
 int L[maxn],R[maxn];
 int root[maxn];
 void insert(int p,int &q,int l,int r,int ql,int qr,int d)
 {
 	q=++cnt,tr[q]=tr[p];tr[q].mx=d;
	if(l>=ql&&r<=qr)	{
		tr[q].lz=d;
		return ;
	}
	int mid=l+r>>1;
	if(ql<=mid)	 insert(tr[p].l,tr[q].l,l,mid,ql,qr,d);
	if(qr>mid)	 insert(tr[p].r,tr[q].r,mid+1,r,ql,qr,d);
 }
 int query(int u,int l,int r,int ql,int qr)
 {
 	int ans=tr[u].lz;
 	if(l>=ql&&r<=qr)
 	return tr[u].mx;
 	int mid=l+r>>1;
 	if(ql<=mid) ans=max(ans,query(tr[u].l,l,mid,ql,qr));
 	if(qr>mid)	ans=max(ans,query(tr[u].r,mid+1,r,ql,qr));
 	return ans;
 }
 int color;
 void dfs1(int u,int fa)
 {
 	L[u]=++color;
 	for(auto j:v[u])
 	{
 		if(j==fa)	continue;
 		dfs1(j,u);
 	}
 	R[u]=color;
 }
 int res=0;
 void dfs2(int u,int fa,int d)
 {
 	
 	dep[u]=dep[fa]+1;
 	int now=max(d,query(root[fa],1,n,L[u],R[u]));
 	res=max(res,dep[u]-now);
 	insert(root[fa],root[u],1,n,L[u],R[u],dep[u]);
 	for(auto j:g[u])	
 	{
 		if(j==fa)	continue;
 		dfs2(j,u,now);
 	}
 }
int main() 
{ 
	// ios::sync_with_stdio(0);
	// cin.tie(0);
	// cout.tie(0);
	int t ;
	cin>>t;
	while(t--)
	{
		
		cin>>n;
		for(int i=0;i<n-1;i++)
		{
			int a,b;
			cin>>a>>b;
			g[a].push_back(b);
			g[b].push_back(a);
		}
		for(int i=0;i<n-1;i++)
		{
			int a,b;
			cin>>a>>b;
			v[a].push_back(b);
			v[b].push_back(a);
		}
		dfs1(1,0);
		dfs2(1,0,0);
		cout<<res<<"\\n";
		for(int i=1;i<=n;i++)	v[i].clear(),g[i].clear();
		cnt=0;	color=0;res=0;
	}
	return 0;
	
}
/**
* In every life we have some trouble
* When you worry you make it double
* Don't worry,be happy.
**/



线段树尺取的话,我们保持窗口要么不变要么加1,很容易发现每次顶多pop一个头节点,注意回溯的时候还原原来的线段树即可。两个复杂度都是nlogn

#pragma GCC target("avx")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
const int N=300010;
vector<int>v[N],g[N];
int idx;
int L[N];
int R[N];
int stk[N];
int bs[N];
int top=0;
int ans;
	int n;
struct node{
	int l;
	int r;
	int mx;
	int lz;
}tr[N<<2];
inline void build(int u,int l,int r)
{
	tr[u]={l,r,0,0};
	if(l==r)	return;
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	
}
inline void pd(int u)
{
	if(tr[u].lz)
	{
		tr[u<<1].lz+=tr[u].lz;
		tr[u<<1|1].lz+=tr[u].lz;
		tr[u<<1].mx+=tr[u].lz;
		tr[u<<1|1].mx+=tr[u].lz;
		tr[u].lz=0;
	}
}
inline void pushup(int u)
{
	tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
}
inline void change(int u,int l,int r,int d)
{
//	cout<<l<<" ->"<<r<<endl;
	if(tr[u].l>=l && tr[u].r<=r){
		tr[u].lz+=d;
		tr[u].mx+=d;
		return ;
	}
	pd(u);
	int mid=tr[u].l+tr[u].r>>1;
	if(l<=mid)	change(u<<1,l,r,d);
	if(r>mid)	change(u<<1|1,l,r,d);
	pushup(u); 
}
inline int query(int u,int l,int r)
{
	if(tr[u].l>=l && tr[u].r<=r)	return tr[u].mx;
	int mid=tr[u].l+tr[u].r>>1;
	pd(u);
	int mx=0;
	if(l<=mid)	mx=max(mx,query(u<<1,l,r));
	if(r>mid)	mx=max(mx,query(u<<1|1,l,r));
	
	return mx;
}
int res=0;
deque<int>q; 
inline void dfs2(int u,int fa)
{
	q.push_back(u);
//	stk[++top]=u;
	int cnt=0;
	int x=1;
	int uu=-1;
	change(1,L[u],R[u],1);
//	cout<<u<<" "<<q.size()<<endl;
	if(tr[1].mx<=1)	res=max(res,(int)q.size());
	else{
//		if(q.size()>res)
		{
			uu=q.front();
//			stk[++top]=q.front();
			change(1,L[uu],R[uu],-1);
			q.pop_front();
		}
	}
	for(auto j:v[u])
	{
		if(j==fa)	continue;
		dfs2(j,u);	
	}
	q.pop_back();
	change(1,L[u],R[u],-1);
	if(uu!=-1)
	change(1,L[uu],R[uu],1),q.push_front(uu);
}
inline void dfs1(int u,int fa)
{
	L[u]=++idx;
	for(auto j:g[u])
	{
		if(j==fa)	continue;		
		dfs1(j,u);
	}
	R[u]=idx;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		while(q.size())	q.pop_back();
		idx=0;
//		cin>>n;
		scanf("%d",&n);	
		
		for(int i=0;i<n-1;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			v[a].push_back(b);
			v[b].push_back(a);
		}
		for(int i=0;i<n-1;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			g[a].push_back(b);
			g[b].push_back(a);
		}
		dfs1(1,-1);
		res=0;
		top=0;
		build(1,1,n);
		dfs2(1,-1);
		
		printf("%d\\n",res);
		for(int i=1;i<=n;i++)	v[i].clear(),g[i].clear();
	}
	
	return 0;
}


以上是关于xay loves trees(主席树dfs序 标记永久化优化)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客多校7 - xay loves trees(dfs序+主席树-标记永久化)

2021牛客暑期多校训练营7 F.xay loves trees 主席树+dfs序

2021牛客暑期多校训练营7xay loves trees(dfs序,维护根出发的链)

2021牛客暑期多校训练营7 F.xay loves trees(主席树+树上尺取)

2021HDU多校10 - 7084 Pty loves string(KMPnext树+主席树+dfs序)

xay loves trees