P4292 [[WC2010] Plan de reconstrucción]

P4292 [[WC2010] Plan de reconstrucción]

División de cadena larga

La idea general de la planificación de la puntuación y la división de la cadena larga ha sido explicada muy claramente por los grandes.
Pero estuve demasiado aturdido por un problema durante mucho tiempo. Estaba
cómo asignar el espacio del árbol de segmento de línea correspondiente a cada subárbol.

Cuando estamos procesando el punto x ,
primero procesamos recursivamente su gran hijo, que es y,
y luego directamente dejemos que x herede los datos de y .

Si la matriz correspondiente ay es larga así,

encontramos que el punto en el árbol de y donde
x es la distancia 1 es y El punto x a una distancia de 0 es un punto a una distancia de 2 es el punto y está a una distancia de 1 ... Entonces, esta es obviamente la secuencia dfs formada al atravesar el primer hijo, donde cada cadena larga corresponde a una sección




Así esta pregunta es construir un árbol de segmento de línea x subárbol del peso máximo del punto con una distancia de n en la dfs secuencia, correspondiente a la dfn [x] + n-ésimo elemento en el árbol de segmento de línea

No entiendo por qué soy tan significativo zhi corrió Zhang tarjetas del lugar por tanto tiempo
la capa más externa de la mitad de un registro de árbol segmento de un registro de
O (n log n-2) O (n log ^ 2n)O ( n l o g2 n)
código final

#include <bits/stdc++.h>
#define N 100100
#define M 200100
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
const double inf=-5e11*1.0;
int n,minn,maxx;
int f[N],nxt[M],data[M],num;
int dfn[N],mdep[N],dep[N],son[N],fa[N],len[N],root,ti;
double rr,mm,lst[N],far[M],dis[N];
int posi[N];
bool ans;
struct _tr{
    
    
	double t[N<<3];
	inline void push_up(int rt){
    
    
		t[rt]=max(t[rt<<1],t[rt<<1|1]);
	}
	inline void updata(int pos,double c,int rt=1,int l=1,int r=n){
    
    
		if(l==r){
    
     t[rt]=max(c,t[rt]); return; }
		if(pos<=mid){
    
     updata(pos,c,lson); }
		else{
    
     updata(pos,c,rson); }
		push_up(rt);
	}
	inline double query(int L,int R,int rt=1,int l=1,int r=n){
    
    
		if(L<=l&&r<=R)return t[rt];
		double res=inf;
		if(L<=mid)res=max(res,query(L,R,lson));
		if(R>mid)res=max(res,query(L,R,rson));
		return res;
	}
	inline void build(int rt=1,int l=1,int r=n){
    
    
		t[rt]=inf;
		if(l==r){
    
     posi[l]=rt; return; }
		build(lson); build(rson);
	}
}q;
void inline add(int x,int y,int z){
    
    
	nxt[++num]=f[x]; f[x]=num; data[num]=y; far[num]=z;
}
inline void dfs(int x){
    
    
	int y;
	for(int i=f[x];i;i=nxt[i]){
    
    
		y=data[i]; if(y==fa[x])continue;
		lst[y]=far[i];
		fa[y]=x; dep[y]=mdep[y]=dep[x]+1; dfs(y);
		if(mdep[x]<mdep[y]){
    
    
			son[x]=y; mdep[x]=mdep[y];
		}
	} 
	len[x]=mdep[x]-dep[x];
}
inline void dfs2(int x){
    
    
	dfn[x]=++ti;
	if(son[x]){
    
     dfs2(son[x]); }
	int y;
	for(int i=f[x];i;i=nxt[i]){
    
    
		y=data[i]; if(y==fa[x]||y==son[x])continue;
		dfs2(y);
	}
}
inline void solve(int x){
    
    
	int y=son[x],o=dfn[x],ql,qr,oo;
	double z;
	q.updata(o,dis[x]);
	if(y){
    
    
		dis[y]=dis[x]+lst[y]-mm;
		solve(y); if(ans==1)return;
	}
	for(int i=f[x];i;i=nxt[i]){
    
    
		y=data[i]; if(y==fa[x]||y==son[x])continue;
		dis[y]=dis[x]+lst[y]-mm; solve(y); if(ans==1)return;
		oo=dfn[y];
		for(int j=0;j<=min(maxx,len[y]);j++){
    
    
			ql=max(minn-1-j,0),qr=min(maxx-1-j,len[x]);
			if(ql>qr)continue;
			z=q.t[posi[oo+j]]-dis[x];
			if(q.query(o+ql,o+qr)-dis[x]+z>=0){
    
    
				ans=1; return; 
			}
		}
		for(int j=0;j<=min(len[y],maxx);j++){
    
    
			ql=1+j;
			if(q.t[posi[oo+j]]>q.t[posi[o+ql]]){
    
     q.updata(o+ql,q.t[posi[oo+j]]); }
		}
	}
	if(len[x]>=minn){
    
    
		if(q.query(o+minn,o+min(len[x],maxx))>=dis[x]){
    
    
			ans=1; return;
		}
	}
}

void get_ans(){
    
    
	double l=0,r=rr;
	while(r-l>0.0002){
    
    
		mm=(l+r)/2.0000;
		ans=0; dis[root]=0; q.build();
		solve(root);
		if(ans){
    
     l=mm; }
		else{
    
     r=mm; }
	} 
	printf("%.3lf",l);
}
int main(){
    
    
//	freopen("test.in","r",stdin);
	scanf("%d %d %d",&n,&minn,&maxx);
	int u,v,z;
	for(int i=1;i<n;i++){
    
    
		scanf("%d %d %d",&u,&v,&z);
		add(u,v,z); add(v,u,z); 
		rr=max((double)z,rr);
	}
	root=rand()%n+1;
	dfs(root); 
	dfs2(root); 
	get_ans();
	return 0;
} 

Supongo que te gusta

Origin blog.csdn.net/RA100FDM/article/details/109207084
Recomendado
Clasificación