A. Tree Master
考虑根号分治,暴力处理。对于一层,设点数为 \(cnt\)。
- 若 \(cnt>\sqrt{n}\),这样的层最多有 \(\sqrt{n}\) 层,每一层最多计算 \(q\) 次,时间复杂度为 \(O(q\sqrt{n})\)。
- 否则 \(cnt\le\sqrt{n}\),进行记忆化,每一层最多计算 \(cnt\choose 2\) 次,最多有 \(\frac{n}{cnt}\) 层,时间复杂度就是 \(O(n\sqrt{n})\) 的。
于是可以通过。空间复杂度 \(O(n)\)。
Code
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define pb push_back
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=1e5+5;
int n,m,fa[maxn],cnt[maxn];
int dep[maxn],bfn[maxn],blen;
ll a[maxn],**mem[maxn];
vector<int> e[maxn],cun[maxn];
queue<int> q;
il ll dfs(int u,int v){if(!u&&!v){return 0;}if(cnt[dep[u]]<=blen&&~mem[dep[u]][bfn[u]][bfn[v]]){return mem[dep[u]][bfn[u]][bfn[v]];}ll res=a[u]*a[v]+dfs(fa[u],fa[v]);if(cnt[dep[u]]<=blen){mem[dep[u]][bfn[u]][bfn[v]]=mem[dep[u]][bfn[v]][bfn[u]]=res;}return res;
}
namespace cplx{bool end;il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){ios::sync_with_stdio(0),cin.tie(0);cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=2;i<=n;i++){cin>>fa[i];e[fa[i]].pb(i);}blen=sqrt(n);q.push(1);while(q.size()){int u=q.front();q.pop();dep[u]=dep[fa[u]]+1;bfn[u]=cnt[dep[u]];cun[dep[u]].pb(u);cnt[dep[u]]++;for(int v:e[u]){q.push(v);}}for(int i=1;i<=n;i++){if(cnt[i]<=blen){mem[i]=new ll*[cnt[i]]();for(int j=0;j<cnt[i];j++){mem[i][j]=new ll[cnt[i]]();for(int k=0;k<cnt[i];k++){mem[i][j][k]=-1;}}}}while(m--){int u,v;cin>>u>>v;cout<<dfs(u,v)<<"\n";}for(int i=1;i<=n;i++){if(cnt[i]<=blen){for(int j=0;j<cnt[i];j++){delete[] mem[i][j];}delete[] mem[i];}}return 0;
}
}
int main(){return asbt::main();}