• 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;
    }
    
  • 相关阅读:
    TSINGSEE青犀视频云边端架构产品EasyNVR/EasyGBS/EasyDSS区别及应用场景介绍
    【解决方案】TSINGSEE青犀视频云边端架构产品如何实现明厨亮灶汇总直播方案?
    【开发记录】RTSP/GB28181/Ehome协议安防视频服务平台EasyCVR使用golang orm操作数据库及基本使用步骤
    TSINGSEE青犀视频云边端架构产品是如何实现视频流传输的?
    【开发记录】安防视频上云服务云平台EasyCVR部署之docker部署步骤参考说明
    TSINGSEE青犀视频+海康合作研发RTMP推流摄像头出现无法推流或无法上线的情况如何配置?
    VC中利用管道技术取得DOS或者命令行以及外部程序的执行结果
    系统程序员成长计划拥抱变化(下)
    系统程序员成长计划Write once, run anywhere(WORA)(下)
    KJava虚拟机hack笔记编译
  • 原文地址:https://www.cnblogs.com/jiangxuancheng/p/14259589.html
Copyright © 2020-2023  润新知