题目描述
题解
大码农题
两点间距离=层数之差绝对值+树上距离+两点路径中据楼梯的最小距离
把到楼梯的距离求出来建Kruskal重构树(其实个人感觉比较像树上的笛卡尔树),把距离从大到小放进去,最后两点间的最小距离就是lca的值
然后分别建原树和重构树的虚树,原树的虚树随便换根dp,重构树的虚树在lca处考虑,对一棵子树加上(其他子树+根)*根权,然后再第二次的时候把tag下传即可
其实并没有https://www.cnblogs.com/gmh77/p/12535146.html难写
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define inf 9223372036854775807ll
#define min(a,b) (a<b?a:b)
#define ll long long
#define file
using namespace std;
struct type{int x,y;} a[1000001];
bool Cmp(type a,type b) {return a.x<b.x;}
int c[200001],dis[200001],Fa[200001],H,n,i,j,k,l,root,Q,m,ls;
ll f[200001],g[200001],size[200001],s1,s2,S1,S2,ans[1000001],Ans,Tr[200001];
int Bggg[2][200001];
bool cmp1(int a,int b) {return Bggg[0][a]<Bggg[0][b];}
bool cmp2(int a,int b) {return Bggg[1][a]<Bggg[1][b];}
void swap(int &x,int &y) {int z=x;x=y;y=z;}
struct tree{
int a[400001][3],ls[200001],A[400001][2],Ls[200001],bg[200001],ed[200001],fa[200001][18];
int d[200001],D[200001],p[200001],len,Len,Tot,root,tot,bzzz,t;
bool bz[200001];
void NEW(int x,int y) {++Len;A[Len][0]=y;A[Len][1]=Ls[x];Ls[x]=Len;}
void New(int x,int y) {NEW(x,y);NEW(y,x);}
void NEW2(int x,int y,int z) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;a[len][2]=z;}
void New2(int x,int y,int z) {NEW2(x,y,z);NEW2(y,x,z);}
bool inc(int x,int y) {return bg[x]<=bg[y] && ed[y]<=ed[x];}
void dfs(int Fa,int t)
{
int i;bg[t]=++Tot;d[t]=d[Fa]+1;fa[t][0]=Fa;
fo(i,1,17) fa[t][i]=fa[fa[t][i-1]][i-1];
for (i=Ls[t]; i; i=A[i][1]) if (A[i][0]!=Fa) dfs(t,A[i][0]);
ed[t]=Tot;
}
int lca(int x,int y)
{
int i;
if (d[x]<d[y]) swap(x,y);
fd(i,17,0) if (d[fa[x][i]]>=d[y]) x=fa[x][i];
fd(i,17,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
if (x!=y) x=fa[x][0];
return x;
}
void init()
{
int i;
dfs(0,root);
fo(i,1,n) Bggg[bzzz][i]=bg[i];
}
void build()
{
int i,j,k=tot;
if (!bzzz) sort(D+1,D+tot+1,cmp1); else sort(D+1,D+tot+1,cmp2);
fo(i,1,k)
{
bz[D[i]]=1;
if (i>1) {j=lca(D[i-1],D[i]);if (!bz[j]) bz[j]=1,D[++tot]=j;}
}
if (!bzzz) sort(D+1,D+tot+1,cmp1); else sort(D+1,D+tot+1,cmp2);
fo(i,1,tot)
{
while (t && !inc(p[t],D[i])) --t;
p[++t]=D[i];
if (t>1) New2(p[t-1],p[t],d[p[t]]-d[p[t-1]]);
}
t=0;
}
void dfs2(int Fa,int t)
{
int i;f[t]=0;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
dfs2(t,a[i][0]);
size[t]+=size[a[i][0]];
f[t]+=f[a[i][0]]+size[a[i][0]]*a[i][2];
}
}
void dfs3(int Fa,int t,ll s)
{
int i;g[t]=f[t]+s;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
dfs3(t,a[i][0],s+f[t]-(size[a[i][0]]*a[i][2]+f[a[i][0]])+(size[p[1]]-size[a[i][0]])*a[i][2]);
}
void dp()
{
int i;
dfs2(0,p[1]);
dfs3(0,p[1],0);
}
void dfs4(int Fa,int t)
{
int i;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
dfs4(t,a[i][0]);
size[t]+=size[a[i][0]];
}
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
Tr[a[i][0]]+=(size[t]-size[a[i][0]])*dis[t];
}
void dfs5(int Fa,int t)
{
int i;f[t]+=size[t]*dis[t]+Tr[t];
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
Tr[a[i][0]]+=Tr[t];
dfs5(t,a[i][0]);
}
}
void work() {dfs4(0,p[1]);dfs5(0,p[1]);}
void clear()
{
int i;
fo(i,1,tot) ls[D[i]]=bz[D[i]]=size[D[i]]=Tr[D[i]]=f[D[i]]=g[D[i]]=0;len=0;tot=0;
}
} t1,t2;
bool cmp(int a,int b) {return dis[a]>dis[b];}
int gf(int t) {if (Fa[t]==t) return t;Fa[t]=gf(Fa[t]);return Fa[t];}
void bfs()
{
int d[200001],i,j,k,l,h=0,t=0;
memset(dis,127,sizeof(dis));
fo(i,1,n) if (c[i]) d[++t]=i,dis[i]=0;
while (h<t)
{
for (i=t1.Ls[d[++h]]; i; i=t1.A[i][1])
if (dis[d[h]]+2<dis[t1.A[i][0]])
{
dis[t1.A[i][0]]=dis[d[h]]+2;
d[++t]=t1.A[i][0];
}
}
}
void build()
{
int a[200001],i,j,k,l,t;
bool bz[200001];
memset(bz,0,sizeof(bz));
fo(i,1,n) a[i]=Fa[i]=i;
sort(a+1,a+n+1,cmp);
fo(t,1,n)
{
bz[a[t]]=1;
for (i=t1.Ls[a[t]]; i; i=t1.A[i][1]) if (bz[t1.A[i][0]]) t2.New(a[t],gf(t1.A[i][0])),Fa[Fa[t1.A[i][0]]]=a[t];
}
t2.root=gf(1);
}
int main()
{
freopen("classroom.in","r",stdin);
#ifdef file
freopen("classroom.out","w",stdout);
#endif
scanf("%d%d",&H,&n);
fo(i,1,n) scanf("%d",&c[i]);
fo(i,1,n-1) scanf("%d%d",&j,&k),t1.New(j,k);
t1.root=1;t1.init();t1.bzzz=0;t2.bzzz=1;
bfs();build();t2.init();
scanf("%d",&Q);
for (;Q;--Q)
{
scanf("%d",&m);s1=s2=S1=S2=0;
memset(ans,0,(m+1)*8);
fo(i,1,m) scanf("%d%d",&a[i].x,&a[i].y),s2+=a[i].x,++S2;
sort(a+1,a+m+1,Cmp);
fo(i,1,m) {if (!t1.bz[a[i].y]) t1.bz[a[i].y]=1,t1.D[++t1.tot]=a[i].y;++size[a[i].y];}
t1.build();t1.dp();
ls=0;
fo(l,1,m)
if (l==m || a[l].x!=a[l+1].x)
{
fo(i,ls+1,l) ans[i]+=(S1*a[i].x-s1)+(s2-S2*a[i].x)+g[a[i].y],s1+=a[i].x,++S1,s2-=a[i].x,--S2;
ls=l;
}
t1.clear();
fo(i,1,m) {if (!t2.bz[a[i].y]) t2.bz[a[i].y]=1,t2.D[++t2.tot]=a[i].y;++size[a[i].y];}
t2.build();t2.work();
fo(i,1,m) ans[i]+=f[a[i].y];
t2.clear();
ls=0;
fo(l,1,m)
if (l==m || a[l].x!=a[l+1].x)
{
fo(i,ls+1,l) {if (!t2.bz[a[i].y]) t2.bz[a[i].y]=1,t2.D[++t2.tot]=a[i].y;++size[a[i].y];}
t2.build();t2.work();
fo(i,ls+1,l) ans[i]-=f[a[i].y];
ls=l;t2.clear();
}
t2.clear();
Ans=inf;
fo(i,1,m) Ans=min(Ans,ans[i]);
printf("%lld\n",Ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}