時間限制: 1 Sec 內存限制: 512 MBc++
題面謝絕公開。ui
我寫的是賽時yy的錯解哇QAQ。僥倖AC了……不過攢一種思路挺好的。spa
開始寫的是純暴力。觀察發現其中的一些點對答案並無貢獻。因此類比並查集想到了路徑壓縮。xml
能夠對於每個點映射一下父節點中第一個比它大的元素,記錄下來。每次跳躍只須要跳向這個節點便可。blog
考慮鏈上相似問題怎麼解決?那顯然是單調棧啊。遞歸
樹上單調棧怎麼搞??ip
因而我開了一個垃圾棧,用來存儲每一次從單調棧裏面pop出來的信息。再對每一次dfs記錄一個lin,爲我當前節點在垃圾棧中「寄存」的元素個數。因爲遞歸順序是肯定的,因此能夠準確「認領」回來。內存
代碼:ci
#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; }