银河战舰 - 长链剖分 - dp

题目大意:给你一颗树,求一条路径使得其LIS最长。 n 2 × 1 0 5 n\le2\times10^5
题解:考虑维护从子树走到当前点的LIS和LDS的那个栈数组,然后长链剖分来保证复杂度即可,其余和朴素LIS类似,合并数组的时候直接取min即可。
注意一些细节。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define N 200010
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct edges{
	int to,pre;
}e[N<<1];int a[N],h[N],etop,son[N],l[N],ans;
inline int add_edge(int u,int v)
{
	return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop;
}
inline int gabs(int x) { return x<0?-x:x; }
inline int sgn(int x) { return x?(x>0?1:-1):0; }
int getl(int x,int fa=0)
{
	for(int i=h[x],y;i;i=e[i].pre) if((y=e[i].to)^fa)
		l[x]=max(l[x],getl(y,x)),(l[y]>l[son[x]]?son[x]=y:0);
	return ++l[x];
}
inline int show(int *f,int n)
{
	debug(n)sp,cerr<<": [ ";
	for(int i=1;i<=n;i++) cerr<<f[i]sp;cerr<<"]"ln;return 0;
}
inline int query(int *f,int n,int x)
{
	int L=1,R=n,mid=(L+R)>>1;x=gabs(x);
	while(L<=R)
	{
		if(sgn(x-gabs(f[mid]))==sgn(f[mid])) L=mid+1;
		else R=mid-1;mid=(L+R)>>1;
	}
	return R;
}
inline int query(int *f,int n,int *g,int m)
{	for(int i=1;i<=m;i++) ans=max(ans,query(f,n,g[i])+i);return 0;	}
inline int ins(int *f,int &n,int x)
{
	int L=1,R=n,mid=(L+R)>>1;
	while(L<=R)
	{
		if(f[mid]<x) L=mid+1;
		else R=mid-1;mid=(L+R)>>1;
	}
	f[L]=x,n=max(n,L);return 0;
}
inline int update(int *f,int &n,int *g,int m)
{
	for(int i=1;i<=min(n,m);i++) f[i]=min(f[i],g[i]);
	for(int i=n+1;i<=m;i++) f[i]=g[i];
	return n=max(n,m),0;
}
int dfs(int x,int *is,int *ds,int &it,int &dt,int fa=0)
{
	if(!son[x]) return is[it=1]=a[x],ds[dt=1]=-a[x],0;
	dfs(son[x],is,ds,it,dt,x),ins(is,it,a[x]),ins(ds,dt,-a[x]);
	for(int i=h[x],y;i;i=e[i].pre)
		if((y=e[i].to)!=son[x]&&e[i].to!=fa)
		{
			int *isy=new int[l[y]+2],*dsy=new int[l[y]+2],ity,dty;
			dfs(y,isy,dsy,ity,dty,x);
			query(ds,dt,isy,ity),query(is,it,dsy,dty);
			ins(isy,ity,a[x]),ins(dsy,dty,-a[x]);
			update(is,it,isy,ity),update(ds,dt,dsy,dty);
		}
	ans=max(ans,max(it,dt));
	return 0;
}
int main()
{
	int n=inn();ans=1;
	for(int i=1;i<=n;i++) a[i]=inn();
	for(int i=1,u,v;i<n;i++) u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
	getl(1);int ans1,ans2;dfs(1,new int[l[1]+2],new int[l[1]+2],ans1,ans2);
	return printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82886113