• GJGHFD的关键点 题解 [倍增+线段树+贪心]


    GJGHFD的关键点

    Description:

    ​ 给定一棵大小为 (n) 的有根树,结点编号从 (1) 开始,并且 (1) 号结点是根.
    ​ 你需要在这颗树上选择 (k) 个结点并将他们设为关键点. 一个点的祖先距离等于从它到根路径上遇到的第一个关键点和它的距离. 当路径上没有关键点时祖先距离为 (+∞) . 一棵树的祖先距离为树上所有点祖先距离的最大值.
    ​ 对所有 (k) = (1, 2, ··· , n) ,求这棵树祖先距离的最小值.

    Input:

    ​ 输入有多组数据.
    ​ 输入的第一行一个整数 (T) ,表示数据组数.
    ​ 对于每组数据,第一行一个整数 (n) ,表示树的大小.
    ​ 接下来一行 (n − 1) 个整数,第 (i) 个整数代表 (i + 1) 号结点的父亲编号.
    ​ 保证输入给出一棵树.

    Output:

    ​ 为了便于输出,对于每组数据,请输出 (k = 1, 2, ··· , n) 的所有答案的和.

    Sample Input:

    2 
    3
    1 2
    3
    1 1
    

    Sample Output:

    3 
    2
    

    Hint:

    ​ 对于(100\%)的数据,$1 leq n leq 2 imes 10^5, $$1 leq sum n leq 1.2 imes10^6$ ,并且至多有 (5) 组数据满足 (n > 1000) .

    ​ 时间限制: (5s)

    ​ 空间限制: (512M)

    题目分析:

    ​ 考虑对于每个 (ans=i) 有多少个 (k) 与之相对应,设其数量为 (k_i) ,则 (ANS = sum (i imes k_i)).

    ​ 那我们再设对于每个 (ans=i) 所需要的 (k) 的最小值为 (mink_i),则容斥一下可得到(k_i=mink_i-mink_{i+1}).

    ​ 考虑如何计算 (mink_i) ,我们可以想到贪心,每次取出树中尚未标记的深度最大的点,跳到该点的 (i) 级祖先,把这个祖先的子树内所有点全部打上标记,表示这些点的祖先距离全部小于等于 (i) 。重复操作直到整棵树都被标记。操作数就是所求的 (mink_i) ,打标记和求深度最大需要用到线段树+dfs序,而跳到 (i) 级祖先需要倍增。

    ​ 代码如下(马蜂很丑,不喜勿喷)——

    #include<bits/stdc++.h>
    #define Tp template<typename T>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define maxn 200005
    #define LL long long
    using namespace std;
    int T,n,tot,maxdep,dep[maxn],f[maxn][20],maxx[maxn<<2],tag[maxn<<2],rk[maxn],dfn[maxn],low[maxn],fir[maxn],nxt[maxn],son[maxn];
    inline void add(int x,int y){son[++tot]=y,nxt[tot]=fir[x],fir[x]=tot;}
    inline void build(int now,int l,int r){
    	if(!tag[now]) return;tag[now]=0;if(l==r){maxx[now]=rk[l];return;}int mid=l+r>>1;build(now<<1,l,mid),build(now<<1|1,mid+1,r);
    	if(dep[maxx[now<<1]]>dep[maxx[now<<1|1]]) maxx[now]=maxx[now<<1];else maxx[now]=maxx[now<<1|1];
    }
    inline void modify(int now,int l,int r,int ll,int rr){
    	if(!maxx[now]) return;tag[now]=1;if(l>=ll&&r<=rr){maxx[now]=0;return;}int mid=l+r>>1;
    	if(mid>=ll) modify(now<<1,l,mid,ll,rr);if(mid<rr) modify(now<<1|1,mid+1,r,ll,rr);
    	if(dep[maxx[now<<1]]>dep[maxx[now<<1|1]]) maxx[now]=maxx[now<<1];else maxx[now]=maxx[now<<1|1];
    }
    inline int jump(int x,int K){for(register int i=17;i>=0;i--) if((1<<i)&K) x=f[x][i];return x;}
    inline void dfs(int x){
    	maxdep=max(maxdep,dep[x]);for(register int i=1;i<=17;i++) f[x][i]=f[f[x][i-1]][i-1];dfn[x]=low[x]=++tot;rk[tot]=x;
    	for(register int i=fir[x];i;i=nxt[i]) dep[son[i]]=dep[x]+1,f[son[i]][0]=x,dfs(son[i]),low[x]=low[son[i]];
    }
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		#define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=Fout)++=ch))
    		char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[25];
    	public:
    		FileInputOutput(void) { Ftop=Fout; Fend=Fout+S; }
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		Tp inline void write(T x,const char& ch)
    		{
    			if (x<0) pc('-'),x=-x; RI ptop=0; while (pt[++ptop]=x%10,x/=10);
    			while (ptop) pc(pt[ptop--]+48); pc(ch);
    		}
    		inline void flush(void)
    		{
    			fwrite(Fout,1,Ftop-Fout,stdout);
    		}
    		#undef tc
    		#undef pc
    }F;
    int main(){
    //	freopen("data.in","r",stdin);
    	F.read(T);while(T--){
    		F.read(n);for(register int i=1;i<=n;i++) fir[i]=0;tot=0;for(register int i=1;i<=n*4;i++) tag[i]=1;
    		for(register int i=2,fa;i<=n;i++) F.read(fa),add(fa,i);maxdep=0,dep[1]=1,tot=0,dfs(1);LL ans=0;for(register int i=maxdep-1;i>=0;i--)
    		{int now=0;build(1,1,n);int x=maxx[1];while(x){now++;x=jump(x,i);if(!x) x=1;modify(1,1,n,dfn[x],low[x]);x=maxx[1];}ans+=now-1;}F.write(ans,'
    ');
    	}
    	return F.flush(),0;
    }
    
  • 相关阅读:
    多节点分布式监控 打造全新信息化港口——大连港集团有限公司
    多节点分布式监控 打造全新信息化港口——大连港集团有限公司
    Linux(Ubuntu)下设置golang环境变量
    刚毕业去面试Python工程师,这几道题太难了,Python面试题No11
    DBA的宿命(困兽之斗)
    AWS RDS强制升级的应对之道——版本升级的最佳实践
    如何使用pygame模块绘制一个窗口并设置颜色
    Java快速排序第二谈
    Ceph 的用户管理与认证
    Kubernetes:如何解决从k8s.gcr.io拉取镜像失败问题
  • 原文地址:https://www.cnblogs.com/jiangxuancheng/p/14259589.html
Copyright © 2020-2023  润新知