「题解」:树
问题 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; }