「题解」:树

问题 A: 树subset

时间限制: 1 Sec  内存限制: 512 MB

题面


题面谢绝公开。

题解


我写的是赛时yy的错解哇QAQ。侥幸AC了……不过攒一种思路挺好的。

开始写的是纯暴力。观察发现其中的一些点对答案并没有贡献。所以类比并查集想到了路径压缩。

可以对于每一个点映射一下父节点中第一个比它大的元素,记录下来。每次跳跃只需要跳向这个节点即可。

考虑链上类似问题怎么解决?那显然是单调栈啊。

树上单调栈怎么搞??

于是我开了一个垃圾栈,用来存储每一次从单调栈里面pop出来的信息。再对每一次dfs记录一个lin,为我当前节点在垃圾栈中“寄存”的元素个数。由于递归顺序是确定的,所以可以准确“认领”回来。

代码:

#include<bits/stdc++.h>
#define rint register int
using namespace std;
const int N=100005;
inline void read(int &a)
{
	a=0;int b=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')b=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){a=(a<<3)+(a<<1)+ch-'0';ch=getchar();}
	a=a*b;return ;
}
int n,q,w[N],f[N],ans,sta[N],tp,rb[N],rp,dep[N];
int v[N<<1],nxt[N<<1],first[N],tot;
inline void build_line(int uu,int vv)
{
	v[++tot]=vv,nxt[tot]=first[uu];
	first[uu]=tot;return ;
}
inline void dfs(int x,int fa,int depth)
{
	int lin=0;dep[x]=depth;
	while(w[sta[tp]]<=w[x]&&tp>0)
		rb[++rp]=sta[tp--],lin++;
	f[x]=sta[tp];sta[++tp]=x;
	for(rint i=first[x];i;i=nxt[i])
		if(v[i]!=fa)dfs(v[i],x,depth+1);
	tp--;
	while(lin)
	{
		sta[++tp]=rb[rp--];
		lin--;
	}
	return ;
}
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("std.out","w",stdout);
	read(n),read(q);
	for(rint i=1;i<=n;++i)read(w[i]);
	for(rint i=1,ST,EN;i<n;++i)
	{
		read(ST),read(EN);
		build_line(ST,EN);
		build_line(EN,ST);
	}
	w[0]=0x7fffffff;dfs(1,0,1);
	for(rint i=1,ui,vi,ci;i<=q;++i)
	{
		read(ui),read(vi),read(ci);ans=0;
		while(dep[ui]>dep[vi]){if(w[ui]>ci)ci=w[ui],ans++;ui=f[ui];}
		if(w[vi]>ci)ans++;printf("%d\n",ans);
	}
	return 0;
}

 

posted @ 2019-10-21 21:38  hzoi_Joe  阅读(124)  评论(0编辑  收藏  举报