板题
这道题应该可以用带权并查集做啊?数据我是用树剖做的,应该没有问题,但带权并查集的代码实在调不出来,求调!
丑陋的代码如下
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define I_love_Foccarus return
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define deap(i,a,b) for(int i=a;i>=b;i--)
#define in(a) a=read()
#define fi first
#define se second
const int N = 1e5 + 5 , maxn = 1e6 + 5;
const int inf = INT_MAX;
inline int read() {
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') {
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9') {
x=x*10+ch-48;
ch=getchar();
}
I_love_Foccarus x*f;
}
void fast() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
struct Edge {
int act , nex;
} edge[N];
int head[N] , eid;
void eadd(int u , int v) {
edge[++eid].act = v , edge[eid].nex = head[u] , head[u] = eid;
}
vector< pair< pair<int , int> , int > >solve[maxn];
vector< pair<int , int> >Q[maxn];
int n , q , f[N] , fa[N] , vis[N] , d[N] , a[N] , ans[maxn] , nx[N] , ny[N] , nz[N];
int find(int x) {
if(fa[fa[x]] != fa[fa[fa[x]]]) {
int root = find(fa[x]);
d[x] += d[fa[x]];
fa[x] = f[root];
}else if(fa[x] != x && fa[x] != fa[fa[x]]){
d[x] += d[fa[x]];
fa[x] = fa[fa[x]];
}
return fa[x];
}
void merge(int x , int y) {
fa[find(x)] = find(y);
}
void Tarjan(int u) {
fa[u] = u , vis[u] = 1 , d[u] = a[u];
for(int i = head[u] ; i ; i = edge[i].nex) {
int v = edge[i].act;
Tarjan(v);
merge(v , u);
}
for(auto v:Q[u]){
if(!vis[v.fi])continue;
solve[find(v.fi)].push_back(make_pair(make_pair(u , v.fi) , v.se));
}
for(auto v:solve[u]){
find(v.fi.fi) , find(v.fi.se);
if(v.fi.fi==v.fi.se) ans[v.se] = a[u];
else if(v.fi.fi!=u&&v.fi.se!=u)
ans[v.se] = d[v.fi.fi] + d[v.fi.se] + a[u];
else ans[v.se] = d[v.fi.fi] + d[v.fi.se];
}
}
signed main() {
//fast();
int root;
in(n);
rep(i , 1 , n)in(a[i]);
rep(i , 1 , n) {
in(f[i]);
if(f[i] != i)eadd(f[i] , i);
else root = i,f[i]=0;
}
in(q);
rep(i , 1 , q) {
int u , v;
in(u) , in(v);
Q[u].push_back(make_pair(v , i));
Q[v].push_back(make_pair(u , i));
}
Tarjan(root);
rep(i , 1 , q) printf("%d\n",ans[i]);
I_love_Foccarus 0;
}