• [HEOI2014]大工程


    Description
    国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。
    我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。
    在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
    现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间新建C(k,2)条新通道。
    现在对于每个计划,我们想知道:
    1.这些新通道的代价和
    2.这些新通道中代价最小的是多少
    3.这些新通道中代价最大的是多少

    Input
    第一行 n 表示点数。
    接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
    点从 1 开始标号。 接下来一行 q 表示计划数。
    对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
    第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。

    Output
    输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。

    Sample Input
    10
    2 1
    3 2
    4 1
    5 2
    6 4
    7
    8 6
    9 7
    10 9
    5
    2
    5 4
    2
    10 4
    2
    5 2
    2
    6 1
    2
    6 1

    Sample Output
    3 3 3
    6 6 6
    1 1 1
    2 2 2
    2 2 2

    HINT
    n<=1000000
    q<=50000并且保证所有k之和<=2*n


    先吐槽一句:这个样例真良心

    标记点个数与(n)同阶?上虚树!建出虚树后考虑求解答案,权值和二次换根即可,最大最小值在dfs的时候记录最大次大,最小次小,然后更新即可

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<3)+(x<<1)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e6;
    int ID[N+10];
    bool cmp(int x,int y){return ID[x]<ID[y];}
    struct S1{
    	int pre[(N<<1)+10],now[N+10],child[(N<<1)+10],tot,Time;
    	int size[N+10],top[N+10],fa[N+10],deep[N+10],Rem[N+10];
    	void join(int x,int y){pre[++tot]=now[x],now[x]=tot,child[tot]=y;}
    	void insert(int x,int y){join(x,y),join(y,x);}
    	void build(int x){
    		deep[x]=deep[fa[x]]+1,size[x]=1;
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa[x])	continue;
    			fa[son]=x,build(son);
    			size[x]+=size[son];
    			if (size[Rem[x]]<size[son])	Rem[x]=son;
    		}
    	}
    	void dfs(int x){
    		if (!x)	return;
    		ID[x]=++Time;
    		top[x]=Rem[fa[x]]==x?top[fa[x]]:x;
    		dfs(Rem[x]);
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==Rem[x]||son==fa[x])	continue;
    			dfs(son);
    		}
    	}
    	int LCA(int x,int y){
    		while (top[x]!=top[y]){
    			if (deep[top[x]]<deep[top[y]])	swap(x,y);
    			x=fa[top[x]];
    		}
    		return deep[x]<deep[y]?x:y;
    	}
    	int dis(int x,int y){return abs(deep[x]-deep[y]);}
    }HLD;//Heavy Light Decomposition
    struct S2{
    	struct node{
    		int Mx,Sx;
    		int Mn,Sn;
    		node(){Mx=Sx=-inf,Mn=Sn=inf;}
    		void clear(){Mx=Sx=-inf,Mn=Sn=inf;}
    		void init(){Mx=Mn=0;}
    	}f[N+10];
    	int pre[(N<<1)+10],now[N+10],child[(N<<1)+10],val[(N<<1)+10];
    	bool mark[N+10];
    	int size[N+10],A[N+10],stack[N+10];
    	int tot,Max,Min,All; ll Ans;
    	void updata(node &x,node y,int v){
    		node z=y; z.Mx+=v,z.Mn+=v;
    		if (x.Mx<z.Mx)	x.Sx=x.Mx,x.Mx=z.Mx;
    		else	if (x.Sx<z.Mx)	x.Sx=z.Mx;
    		
    		if (x.Mn>z.Mn)	x.Sn=x.Mn,x.Mn=z.Mn;
    		else	if (x.Sn>z.Mn)	x.Sn=z.Mn;
    	}
    	void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
    	void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
    	void insert(int x,int y){insert(x,y,HLD.dis(x,y));}
    	void rebuild(int m){
    		int top=0; tot=0;
    		sort(A+1,A+1+m,cmp);
    		stack[++top]=1;
    		for (int i=1;i<=m;i++){
    			int x=A[i],lca=HLD.LCA(stack[top],x);
    			if (x==1)	continue;
    			if (lca==stack[top]){
    				stack[++top]=x;
    				continue;
    			}
    			while (true){
    				int y=stack[top-1];
    				if (ID[y]>=ID[lca]){
    					insert(stack[top--],y);
    					continue;
    				}else{
    					if (lca==stack[top])	break;
    					insert(stack[top],lca);
    					stack[top]=lca; break;
    				}
    			}
    			stack[++top]=x;
    		}
    		while (top>1){
    			insert(stack[top],stack[top-1]);
    			top--;
    		}
    	}
    	void dfs(int x,int fa){
    		f[x].clear(); size[x]=mark[x];
    		if (mark[x])	f[x].init();
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa)	continue;
    			dfs(son,x),size[x]+=size[son];
    			updata(f[x],f[son],val[p]);
    		}
    		Max=max(Max,f[x].Mx+f[x].Sx);
    		Min=min(Min,f[x].Mn+f[x].Sn);
    	}
    	void sum(int x,int fa){
    		for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
    			if (son==fa)	continue;
    			sum(son,x);
    			Ans+=1ll*size[son]*(All-size[son])*val[p];
    		}
    		now[x]=0;
    	}
    	void work(){
    		int m=read();
    		for (int i=1;i<=m;i++)	mark[A[i]=read()]=1;
    		rebuild(m),Max=-inf,Min=inf;
    		dfs(1,0),All=size[1],Ans=0,sum(1,0);
    		printf("%lld %d %d
    ",Ans,Min,Max);
    		for (int i=1;i<=m;i++)	mark[A[i]]=0;
    	}
    }T;
    int main(){
    	int n=read();
    	for (int i=1;i<n;i++){
    		int x=read(),y=read();
    		HLD.insert(x,y);
    	}
    	HLD.build(1),HLD.dfs(1);
    	int m=read();
    	for (int i=1;i<=m;i++)	T.work();
    	return 0;
    }
    
  • 相关阅读:
    spring boot 启动类 添加组件
    spirng boot 添加过滤器
    spring cloud spring-hystrix 缓存
    spring cloud spring-hystrix
    spring cloud spirng整合feign
    spring cloud feign
    cxf-client
    spring cloud客户端启用负载均衡
    spring cloud 负载均衡自定义
    VS2013 配置pthread
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10249082.html
Copyright © 2020-2023  润新知