80 求助
查看原帖
80 求助
340632
Cry_For_theMoon楼主2021/4/8 21:45

rt

思路是单调队列,LOJ 1 WA 3 RE,Luogu 2 WA 2 RE

(主要WA我还能接受但是RE不知道为什么,调了一下发现是在找环的部分但我并没发现有什么会影响的)

QwQ


#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define per(i,a,b) for(ll i=(a);i>=(b);i--)
#define op(x) ((x&1)?x+1:x-1)
#define odd(x) (x&1)
#define even(x) (!odd(x))
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define mid(x) ((l[x]+r[x])>>1)
#define lowbit(x) (x&-x)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define next Cry_For_theMoon
#define il inline
#define pb(x) push_back(x)
#define is(x) insert(x)
#define sit set<int>::iterator
#define mapit map<int,int>::iterator
#define pi pair<int,int>
#define ppi pair<int,pi>
#define pp pair<pi,pi>
#define fr first
#define se second
#define vit vector<int>::iterator
#define mp(x,y) make_pair(x,y)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
using namespace std;
const ll MAXN=1e5+10,MAXM=2e5+10,INF=1e16;
ll n,a,b,l,ans,ans2=INF;
struct Edge{
	ll u,v,w;
}edge[MAXM];
ll first[MAXN],next[MAXM],tot;
ll fa[MAXN],r[MAXN],rv[MAXN],cnt;
ll tag[MAXN],top[MAXN],depth[MAXN],maxdepth[MAXN];
ll sum[MAXN],suf[MAXN],lim[MAXN];
pi pre[MAXN];
int Find(int x){
	if(fa[x]==x)return x;
	return fa[x]=Find(fa[x]);
}
void addedge(int u,int v,int w){
	edge[++tot].u=u;edge[tot].v=v;edge[tot].w=w;
	next[tot]=first[u];first[u]=tot;
}
void findRing(int u){
	if(u==b){
		r[++cnt]=b;rv[cnt]=pre[b].se;
		int tmp=b;
		while(tmp!=a){
			r[++cnt]=pre[tmp].fr;rv[cnt]=pre[pre[tmp].fr].se;
			tmp=pre[tmp].fr;
		}
		return;
	}
	for(int j=first[u];j;j=next[j]){
		int v=edge[j].v;
		if(v==pre[u].fr)continue;
		pre[v]=mp(u,edge[j].w);
		findRing(v);
	}
}
void outTree(int u){
	ll max1=-INF,max2=-INF;
	for(int j=first[u];j;j=next[j]){
		int v=edge[j].v;
		if(tag[v] || v==top[u])continue;
		top[v]=u;
		depth[v]=depth[u]+edge[j].w;
		outTree(v); 
		maxdepth[u]=Max(maxdepth[u],maxdepth[v]+edge[j].w);
		if(maxdepth[v]+edge[j].w>max1)max2=max1,max1=maxdepth[v]+edge[j].w;
		else if(maxdepth[v]>max2)max2=maxdepth[v]+edge[j].w;
	}
	ans=Max(ans,Max(max1,max1+max2));
}
ll q1[MAXM],q2[MAXM],head1,rear1,head2,rear2;
int main(){
	scanf("%lld",&n);
	rep(i,1,n)fa[i]=i;
	rep(i,1,n){
		scanf("%lld%lld%lld",&a,&b,&l);
		if(Find(a)==Find(b)){
			//断环成链 
			findRing(a);
			rv[cnt]=l;
			continue;
		}
		fa[Find(a)]=Find(b);
		addedge(a,b,l);addedge(b,a,l);
	}
	//计算每一个外向树的答案 
	rep(i,1,cnt)tag[r[i]]=1;
	rep(i,1,cnt){
		int rt=r[i];
		outTree(rt);
	}
	rep(i,1,cnt)r[i+cnt]=r[i],rv[i+cnt]=rv[i];
	cnt*=2;
	rep(i,1,cnt)sum[i]=sum[i-1]+rv[i-1];
	//维护前n个d+sum的最大值,d-sum的最大值
	rep(i,1,cnt){
		while(head1<rear1 && q1[head1]+(cnt/2)<=i)head1++;
		while(head2<rear2 && q2[head2]+(cnt/2)<=i)head2++;
		while(head1<rear1 && sum[q1[rear1-1]]+maxdepth[r[q1[rear1-1]]]<sum[i]+maxdepth[r[i]])rear1--;
		q1[rear1++]=i;
		if(head1<rear1 && head2<rear2 && i>(cnt/2)){
			int R=q1[head1],L=q2[head2];
			//[L,R]这一段 
			if(L!=R){ans2=Min(ans2,maxdepth[r[L]]+maxdepth[r[R]]+sum[R]-sum[L]);}
			else{
				ll tmp=0;
				if(head1+1<rear1){
					R=q1[head1+1];
					tmp=Max(tmp,maxdepth[r[L]]+maxdepth[r[R]]+sum[R]-sum[L]);
				//	printf("[%d,%d] %d\n",L,R,maxdepth[r[L]]);
				}
				if(head2+1<rear2){
					L=q2[head2+1],R=q1[head1];
					tmp=Max(tmp,maxdepth[r[L]]+maxdepth[r[R]]+sum[R]-sum[L]);
				//	printf("[%d,%d] %d\n",L,R,maxdepth[r[L]]);
				}
			//	printf("tmp:%lld\n",tmp);
				ans2=Min(ans2,tmp);
			}
		}
		while(head2<rear2 && maxdepth[r[q2[rear2-1]]]-sum[q2[rear2-1]] < maxdepth[r[i]]-sum[i])rear2--;
		q2[rear2++]=i;
	} 
	ans=Max(ans,ans2);
	printf("%.1f\n",(double)(ans)/2);
	return 0;
}
2021/4/8 21:45
加载中...