zoukankan      html  css  js  c++  java
  • bzoj3611: [Heoi2014]大工程

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3611

    思路:构建虚树DP

    首先这种题有一个特征,就是所有询问的总点数是O(n)的

    那么就可以考虑对每次询问建一棵虚树,再在虚树上DP。

    那么我们对于每次询问,就不一定要把整棵树建出来,而是只要管一部分点即可

    比如u,v两点之间没有其他询问点,那么我们就可以把uv直接连起来,中间的点是什么我们并不关心。

    我们只要建出这样一棵树即可:只含当前询问点和它们的lca,并且相对位置关系不变

    举个例子:原树是这样的,假如选了1、5、8、10号节点


    构建出来的虚树就是:

    怎样构建虚树?

    先对原图做一边dfs预处理,得出dfn和一些乱七八糟的东西。

    对于每次询问,先把所有询问点按dfn排序,一个一个插入。

    我们要用栈维护一个叫“最右链”的东西,就是最右边的一条链...

    每次和最右链的最深的一个点求lca,并动态维护之。

    如果栈为空,直接加进栈,

    否则求出栈顶元素stk[top]和当前点的lca

    如果dfn[lca]<dfn[stk[top]],那就一直弹栈直到dfn[lca]>=dfn[stk[top]],因为这些点都不会在新的最右链里。

    (记得特判lca是否已在栈中)

    看图直观理解就是左边的点与当前点求lca不会贡献出新的点,所以只用管最右链即可



    这样我们每次就可以O(m)的构建虚树了,这也是为什么这些题都有Σq[i]<=O(n)的限制。

    用虚树还要满足一个条件,就是要维护的信息

    例如,和,最大,最小,都有类似于前缀和的性质,

    就是我们可以从v(u的后代)直接求出u的答案,而不需要遍历u到v的所有边

    否则虚树就没有降低复杂度,因为每次还是要在原树上走。


    对于这题,剩下的只有在虚树上treeDP了。

    记录f[i]表示在i的子树中的路径总长,siz[i]表示i的子树中询问点的个数

    maxs[i]表示i子树中询问点到根的最长路长,mins[i]同理。

    转移很显然 f[i]=f[son[i]]+siz[son[y]]*(cnt-siz[son[y]])*dis(i,son[i])   (cnt是此次询问总点数)

    对于maxs[i]

    如果i是询问点,那就只要在子树中找另一个询问点即可

    即我们可以直接用maxs[i]更新答案。

    否则我们要找两个点,用maxs[i]+maxs[son[i]]+dis(i,son[i])更新答案

    最小同理


    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    const int maxn=1000010,maxm=maxn<<1,maxk=23,inf=1e9;
    using namespace std;
    int n,q,dis[maxn],dfn[maxn],tim,dep[maxn],fa[maxn][maxk],num,poi[maxn];
    int stk[maxn],top,siz[maxn],maxs[maxn],mins[maxn],ans1,ans2;
    ll f[maxn];bool bo[maxn];
    bool cmp(int a,int b){return dfn[a]<dfn[b];}
    struct Tgraph{
    	int pre[maxm],now[maxn],son[maxm],tot;
    	void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
    	void dfs1(int x){
    		dfn[x]=++tim;
    		for (int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    		for (int y=now[x];y;y=pre[y]) if (son[y]!=fa[x][0])
    			dis[son[y]]=dis[x]+1,dep[son[y]]=dep[x]+1,fa[son[y]][0]=x,dfs1(son[y]);
    	}
    	void dfs2(int x){
    		siz[x]=bo[x],maxs[x]=0,mins[x]=inf,f[x]=0;
    		for (int y=now[x];y;y=pre[y]){
    			int d=dis[son[y]]-dis[x];
    			dfs2(son[y]),siz[x]+=siz[son[y]];
    			ans1=min(ans1,mins[x]+mins[son[y]]+d),mins[x]=min(mins[x],mins[son[y]]+d);
    			ans2=max(ans2,maxs[x]+maxs[son[y]]+d),maxs[x]=max(maxs[x],maxs[son[y]]+d);
    			f[x]+=f[son[y]]+1ll*siz[son[y]]*(num-siz[son[y]])*d;
    		}
    		if (bo[x]) ans1=min(ans1,mins[x]),ans2=max(ans2,maxs[x]),mins[x]=0;
    		now[x]=0;
    	}
    }g1,g2;
    
    int lca(int a,int b){
    	if (dep[a]<dep[b]) swap(a,b);
    	for (int h=dep[a]-dep[b],i=20;i>=0;i--) if (h>=(1<<i)) h-=(1<<i),a=fa[a][i];
    	if (a==b) return a;
    	for (int i=20;i>=0;i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
    	return fa[a][0];
    }
    
    void work(){
    	top=0;
    	for (int i=1;i<=num;i++){
    		if (!top){stk[++top]=poi[i];continue;}
    		int u=lca(stk[top],poi[i]);
    		while (dfn[u]<dfn[stk[top]]){
    			if (dfn[u]>=dfn[stk[top-1]]){
    				g2.add(u,stk[top]);
    				if (stk[--top]!=u) stk[++top]=u;
    				break;
    			}
    			g2.add(stk[top-1],stk[top]),top--;
    		}
    		stk[++top]=poi[i];
    	}
    	while (top>1) g2.add(stk[top-1],stk[top]),top--;
    	ans1=inf,ans2=0,g2.dfs2(stk[1]);
    	printf("%lld %d %d
    ",f[stk[1]],ans1,ans2);
    	for (int i=1;i<=num;i++) bo[poi[i]]=0;g2.tot=0;
    }
    
    int main(){
    	scanf("%d",&n);
    	for (int i=1,a,b;i<n;i++) scanf("%d%d",&a,&b),g1.add(a,b),g1.add(b,a);
    	g1.dfs1(1),scanf("%d",&q);
    	for (int i=1;i<=q;i++){
    		scanf("%d",&num);
    		for (int j=1;j<=num;j++) scanf("%d",&poi[j]),bo[poi[j]]=1;
    		sort(poi+1,poi+1+num,cmp),work();
    	}
    	return 0;
    }


  • 相关阅读:
    [N1CTF 2018]eating_cms 敏感文件扫描+php伪协议利用
    文件包含漏洞(总结)+常见的getshell+PHP伪协议
    laravel安装jwt-auth及验证(实例)
    理解 PHP 8 的 JIT
    Laravel 文件缓存也可以快得飞起,tmpfs 了解一下
    关于 Laravel ORM 对 Model::find 方法进行缓存
    在 Laravel 7 中优雅使用 UUID 教程
    PestPHP 正式开源,一个优雅的测试框架
    PHP 8 还有半年就要来了, 来看看有哪些新特性
    Redis持久化过程的监控及优化
  • 原文地址:https://www.cnblogs.com/thythy/p/5493493.html
Copyright © 2011-2022 走看看