85求调,玄关
查看原帖
85求调,玄关
361103
awa水水湖awa楼主2024/4/27 21:01
#include<bits/stdc++.h>
using namespace std;
long long n,SUM;
struct island
{
	long long to,len,rudu,maxx1,maxx2;
}is[3000006];
struct HUAN
{
	long long len,sta,sum;
}huan[3000005];
long long h,Huan[3000005],Bian[3000005],H;
struct QQQQQ
{
	long long sum,i;
};
long long head[6000006],to[6000006],num[6000006],len[6000006],tot;
bool visit[3000006];
long long f[3000006];
long long ans;
void add_edge(long long x,long long y,long long k)
{
	tot++;
	len[tot]=k;
	num[tot]=y;
	to[tot]=head[x];
	head[x]=tot;
}
long long dfs(long long p)
{
	for(long long i=head[p];i;i=to[i])
	{
		if(!visit[num[i]] && is[num[i]].rudu==1)
		{
			visit[num[i]]=true;
			Huan[++H]=num[i];
			Bian[H]=len[i];
			huan[h].len++;
			huan[h].sum+=len[i];
			return dfs(num[i]);
		}
		else
		{
			if(visit[num[i]] && is[num[i]].rudu==1)
			{
				huan[h].sum+=len[i];
				return len[i];
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	for(long long i=1;i<=n;i++)
	{
		cin>>is[i].to>>is[i].len;
		add_edge(i,is[i].to,is[i].len);
		is[is[i].to].rudu++;
	}
	queue<long long> Q;
	for(long long i=1;i<=n;i++)
	{
		if(is[i].rudu==0)
		{
			Q.push(i);
		}
	}
	while(!Q.empty())
	{
		long long p=Q.front();
		Q.pop();
		for(long long i=head[p];i;i=to[i])
		{
			is[num[i]].rudu--;
			if(len[i]+is[i].maxx1>is[num[i]].maxx1)
			{
				is[num[i]].maxx2=is[num[i]].maxx1;
				is[num[i]].maxx1=len[i]+is[i].maxx1;
			}
			else if(len[i]+is[i].maxx1>is[num[i]].maxx2)is[num[i]].maxx2=len[i]+is[i].maxx1;
			if(is[num[i]].rudu==0)
			{
				Q.push(num[i]);
			}
		}
	}
	for(long long i=1;i<=n;i++)
	{
		visit[i]=false;
	}
	for(long long i=1;i<=n;i++)
	{
		if(is[num[i]].rudu==1 && !visit[num[i]])
		{
			huan[++h].sta=H+1;
			huan[h].len++;
			visit[num[i]]=true;
			Huan[++H]=num[i];
			Bian[H]=dfs(num[i]);
		}
	}
	queue<QQQQQ> m1,m2;//m1:i-disi,m2:i+disi
	QQQQQ PUT;
	for(long long i=1;i<=h;i++)
	{
		for(long long j=huan[i].sta;j<=huan[i].len+huan[i].sta-1;j++)
		{
			ans=max(ans,is[Huan[j]].maxx1+is[Huan[j]].maxx2);
		}
		PUT.sum=is[Huan[huan[i].sta]].maxx1;
		PUT.i=1;
		m1.push(PUT);
		m2.push(PUT);
		for(long long j=2;j<huan[i].len*2;j++)
		{
			long long I=(((j-1)%huan[i].len+1)-1)+huan[i].sta;
			if(I-huan[i].sta+1==1)f[I]=f[huan[i].sta+huan[i].len-1]+Bian[I];
			else f[I]=f[I-1]+Bian[I];
			while(!m1.empty() && ((j-m1.front().i>=huan[i].len)))
			{
				m1.pop();
			}
			long long Front1=m1.front().sum;
			ans=max(ans,is[Huan[I]].maxx1+f[I]+Front1);
			while(!m1.empty() && ((m1.front().sum)<=is[Huan[I]].maxx1-f[I]))
			{
				m1.pop();
			}
			PUT.sum=is[Huan[I]].maxx1-f[I];
			PUT.i=j;
			m1.push(PUT);
			
			while(!m2.empty() && ((j-m2.front().i>=huan[i].len)))
			{
				m2.pop();
			}
			long long Front2=m2.front().sum;
			ans=max(ans,is[Huan[I]].maxx1-f[I]+Front2+huan[i].sum);
			while(!m2.empty() && ((m2.front().sum)<=is[Huan[I]].maxx1+f[I]))
			{
				m2.pop();
			}
			PUT.sum=is[Huan[I]].maxx1+f[I];
			PUT.i=j;
			m2.push(PUT);
		}
		while(!m1.empty())
		{
			m1.pop();
		}
		while(!m2.empty())
		{
			m2.pop();
		}
		SUM+=ans;
		ans=0;
	}
	cout<<SUM;
	
	return 0;
}

具体思路是先处理每个环上的点的子树最大值和第二大值,然后在环上dp,分别处理每个环,最后累加答案

2024/4/27 21:01
加载中...