• CF Contest 526 G. Spiders Evil Plan 长链剖分维护贪心


    LINK:Spiders Evil Plan

    非常巧妙的题目。

    选出k条边使得这k条边的路径覆盖x且覆盖的边的边权和最大。

    类似于桥那道题还是选择2k个点 覆盖x那么以x为根做长链剖分即可。

    不过这样过不了。

    还是考虑树的直径 可以发现覆盖x的那些点一定有一个是树的直径的两端之一。

    所以我们直接对两条直径分别做这个东西然后想办法覆盖x.

    如果y条边x还没被覆盖。

    可以发现此时调整只有两种情况。

    1. 去掉长度最小的链然后把x所在的最长链加上去。

    2. 可以把x向上的被加入的链的下半部分去掉换成x.

    由于边权不为1 所以无法直接跳长链。

    考虑倍增即可。

    const int MAXN=100010;
    int n,len,Q;
    int Log[MAXN];
    int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],e[MAXN<<1];
    inline void add(int x,int y,int z)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    	e[len]=z;
    }
    struct wy
    {
    	int d[MAXN],dis[MAXN],son[MAXN],mx[MAXN],ans[MAXN],c[MAXN];
    	int f[MAXN][20],cnt,rt,maxx;;
    	pii s[MAXN];
    	inline void dfs(int x,int fa,int op)
    	{
    		if(op)
    		{
    			f[x][0]=fa;mx[x]=dis[x];
    			d[x]=d[fa]+1;
    			rep(1,Log[d[x]],i)f[x][i]=f[f[x][i-1]][i-1];
    		}
    		if(!op&&dis[x]>dis[rt]){rt=x;}
    		go(x)
    		{
    			if(tn==fa)continue;
    			dis[tn]=dis[x]+e[i];
    			dfs(tn,x,op);
    			if(op&&mx[tn]>mx[x])
    			{
    				mx[x]=mx[tn];
    				son[x]=tn;
    			}
    		}
    	}
    	inline void dp(int x,int fa)
    	{
    		if(x==fa){s[++cnt]=mk(mx[x]-dis[f[x][0]],x);}
    		if(son[x])dp(son[x],fa);
    		go(x)if(tn!=f[x][0]&&tn!=son[x])dp(tn,tn);
    	}
    	inline void init(int x)
    	{
    		dfs(x,0,0);dis[rt]=0;
    		dfs(rt,0,1);dp(rt,rt);
    		sort(s+1,s+cnt+1);
    		for(int i=1,j=cnt;i<=cnt;++i,--j)
    		{
    			ans[i]=ans[i-1]+s[j].F;
    			for(int k=s[j].S;k;k=son[k])c[k]=i;
    		}
    	}
    	inline int calc1(int x,int y)//x所在长链替换y-1条长链
    	{
    		--y;
    		int w=x;
    		fep(Log[d[w]],0,i)if(c[f[w][i]]>y)w=f[w][i];
    		w=f[w][0];return ans[y]+mx[x]-dis[w];
    	}
    	inline int calc2(int x,int y)//向上的第一个长链的下半部分被替换掉.
    	{
    		int w=x;
    		fep(Log[d[x]],0,i)if(c[f[w][i]]>y)w=f[w][i];
    		w=f[w][0];return ans[y]+mx[x]-mx[w];
    	}
    	inline int query(int x,int y)
    	{
    		y=y*2-1;
    		if(y>=cnt)return ans[cnt];
    		if(c[x]<=y)return ans[y];
    		return max(calc1(x,y),calc2(x,y));
    	}
    	
    }t[2];
    int main()
    {
    	freopen("1.in","r",stdin);
    	get(n);get(Q);
    	rep(2,n,i)
    	{
    		int get(x),get(y),get(z);
    		add(x,y,z);add(y,x,z);
    		Log[i]=Log[i>>1]+1;
    	}
    	t[0].init(1);t[1].init(t[0].rt);
    	int ans=0;
    	rep(1,Q,i)
    	{
    		int x,y;
    		get(x);get(y);
    		x=(x+ans-1)%n+1;
    		y=(y+ans-1)%n+1;
    		ans=max(t[0].query(x,y),t[1].query(x,y));
    		put(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    java8 stream().map().collect()用法
    Java中Collections的emptyList、EMPTY_LIST详解
    zxing实现java二维码生成和解析
    机器学习与数据挖掘—K邻近算法(KNN)
    第一个Web项目(IDEA)
    Ucore操作系统实验-实验课程设计
    数据挖掘与机器学习--损失函数
    机器数据挖掘--常见监督学习算法以及数据挖掘流程
    Tomcat安装-环境变量配置-启动-关闭
    操作系统实验教程(Ucore)--Lab6
  • 原文地址:https://www.cnblogs.com/chdy/p/12770291.html
Copyright © 2020-2023  润新知