ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF526G Spiders Evil Plan

2020-03-24 14:03:05  阅读:308  来源: 互联网

标签:rt 长链 ch r1 int CF526G Evil Spiders ans


cf

经过一番思考,可以发现原问题等价于选出\(2y\)个叶子,使得他们两两之间路径的并包含\(x\)且边权和最大(如果\(2y\ge\)总叶子个数则直接输出所有边权值之和).这是因为你可以通过让\(2y\)个叶子两两匹配得到\(y\)条路径,然后\(y\)条路径的并也就是这些叶子两两之间路径的并

先考虑暴力(?),对于一个\(x\)依次算出\(y=1,2,3...\)的答案.\(y=1\)时,答案就是把\(x\)作为根时,最大的 两个不同子树到根的最长链之和的.可以发现这两条最长链中有一条的端点一定是树直径的两端点之一,并且这条链一定经过直径的中点.如果我们把树的根改为树直径的中点,那么询问\((x,1)\)的答案就是\(x\)到直径两端点的距离最大值加\(x\)子树内到根最长链长度

然后考虑\(y\)每次加\(1\),贪心的考虑就是每次选出两个叶子使得路径并的增加量最大.由于每次选的叶子都是使得答案增量最大的,且选完后会使得一些其他叶子的贡献减少,如果我们对于 删去\(y=1\)时选的链剩下的树 做长链剖分,可以发现每次选的叶子代表的都是剩余的最长的长链,所以对于\(x\),只要把所有长链长度丢进一个线段树,就可以通过线段树二分的手段求出前\(k\)大的长度之和

每次长链剖分是不行的.这里我们先对以直径中点为根的树长链剖分,然后考虑其他的点.一个点\(x\)会先删掉\(y=1\)时的链,这条不在长链集合中的链一定是原来若干条长链的前缀+\(x\)所在长链+直径对应两个长链之一.我们dfs整棵树,如果点\(x\)和父亲在一条长链上,那么他们对应长链集合不变,否则会加入父亲长链剩余的下半部分,以及删去\(x\)所在长链,所以这里可以使用可持久化线段树来维护

#include<bits/stdc++.h>
#define LL long long
#define db long double

using namespace std;
const int N=1e5+10,mod=998244353;
int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
    return x*w;
}
int to[N<<1],nt[N<<1],w[N<<1],hd[N],tot=1;
void adde(int x,int y,int z)
{
    ++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
    ++tot,to[tot]=x,nt[tot]=hd[y],w[tot]=z,hd[y]=tot;
}
int s1[N*70],s2[N*70],ch[N*70][2],rt[N],tt,vl=1,vr=1e8;
void inst(int o1,int o2,int x,int dx)
{
    s1[o1]=s1[o2]+dx,s2[o1]=s2[o2]+x*dx;
    int l=vl,r=vr;
    while(l<r)
    {
    	int mid=(l+r)>>1;
    	if(x<=mid)
    	{
    	    ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
    	    o1=ch[o1][0],o2=ch[o2][0];
    	    r=mid;
    	}
    	else
    	{
    	    ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
    	    o1=ch[o1][1],o2=ch[o2][1];
    	    l=mid+1;
    	}
	s1[o1]=s1[o2]+dx,s2[o1]=s2[o2]+x*dx;
    }
}
int a1,a2;
int q1(int o,int l,int r,int k)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(s1[ch[o][1]]<k)
    {
    	a1+=s1[ch[o][1]],a2+=s2[ch[o][1]];
    	return q1(ch[o][0],l,mid,k-s1[ch[o][1]]);
    }
    else return q1(ch[o][1],mid+1,r,k);
}
int n,q,dt[N],r1,r2,fa[N],fw[N],de[N],dp[N],hs[N],top[N],zl[N],fy;
void dfs0(int x)
{
    dt[x]=max(dt[x],de[x]);
    if(de[r1]<de[x]) r1=x;
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
    	if(y==fa[x]) continue;
    	fa[y]=x,de[y]=de[x]+w[i],dfs0(y);
    }
}
void dfs1(int x)
{
    dp[x]=de[x];
    for(int i=hd[x];i;i=nt[i])
    {
        int y=to[i];
        if(y==fa[x]) continue;
        fa[y]=x,fw[y]=w[i],de[y]=de[x]+w[i],dfs1(y);
        if(dp[y]>dp[x]) dp[x]=dp[y],hs[x]=y;
    }
}
void dfs2(int x)
{
    if(hs[x]) top[hs[x]]=top[x],dfs2(hs[x]);
    for(int i=hd[x];i;i=nt[i])
    {
	    int y=to[i];
	    if(y==fa[x]||y==hs[x]) continue;
    	top[y]=y,dfs2(y);
    }
}
void dfs3(int x)
{
    for(int i=hd[x];i;i=nt[i])
    {
    	int y=to[i];
    	if(y==fa[x]) continue;
    	rt[y]=rt[x];
    	if(y!=hs[x])
    	{
    	    int las=rt[y];
    	    inst(rt[y]=++tt,las,x==r1?zl[fy]:dp[x]-de[x],1);
    	    las=rt[y];
    	    inst(rt[y]=++tt,las,zl[y],-1);
    	}
    	dfs3(y);
    }
}

int main()
{
    //////
    n=rd(),q=rd();
    for(int i=1;i<n;++i)
    {
        int x=rd(),y=rd(),z=rd();
    	adde(x,y,z);
    }
    dfs0(1);
    r2=r1,r1=0,fa[r2]=de[r2]=0,dfs0(r2);
    r2=r1,r1=0,fa[r2]=de[r2]=0,dfs0(r2);
    int nl=de[r1];
    while(fa[r1]!=r2&&de[r1]>nl-de[r1]) r1=fa[r1];
    fa[r1]=de[r1]=0;
    dfs1(r1),top[r1]=r1,dfs2(r1);
    for(int i=1;i<=n;++i)
	if(top[i]==i)
	{
	    int las=rt[0];
	    inst(rt[0]=++tt,las,zl[i]=dp[i]-de[i]+fw[i],1);
	}
    int nm=s1[rt[0]],zans=s2[rt[0]],las;
    inst(rt[r1]=++tt,rt[0],zl[r1],-1),dt[r1]=nl;
    las=rt[r1],inst(rt[r1]=++tt,las,nl-zl[r1],-1);
    for(int i=1;i<=n;++i)
	if(i!=r1) dt[i]+=dp[i]-de[i];
    for(int i=hd[r1];i;i=nt[i])
    {
    	int y=to[i];
    	if(y==hs[r1]) continue;
    	fy=dp[fy]>dp[y]?fy:y;
    }
    dfs3(r1);
    int ans=0;
    while(q--)
    {
    	int x=(rd()+ans-1)%n+1,y=((rd()+ans-1)%n+1)*2;
    	if(y>=nm) ans=zans;
    	else
    	{
    	    y-=2,ans=dt[x];
    	    a1=a2=0;
    	    int nv=q1(rt[x],vl,vr,y);
    	    ans+=a2+(y-a1)*nv;
    	}
    	printf("%d\n",ans);
    }
    return 0;
}

标签:rt,长链,ch,r1,int,CF526G,Evil,Spiders,ans
来源: https://www.cnblogs.com/smyjr/p/12558655.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有