「题解」:树
问题 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;
}
浙公网安备 33010602011771号