6642. 【GDOI20205.20模拟】classroom

题目描述


题解

大码农题

两点间距离=层数之差绝对值+树上距离+两点路径中据楼梯的最小距离

把到楼梯的距离求出来建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;
}

猜你喜欢

转载自www.cnblogs.com/gmh77/p/12967295.html