#欧拉序,线段树#洛谷 6845 [CEOI2019] Dynamic Diameter

题目

动态修改边权,强制在线询问树的直径。


分析

\(dis[x]\) 表示 \(x\) 到1号点的距离。

那么树的直径就可以表示成 \(dis[x]+dis[y]-2*dis[lca]\)

只需要保证 \(lca\) 被夹在 \(x,y\) 之间,欧拉序可以满足这样的条件。

用欧拉序将树拍成一个序列,也就是要询问 \(\max_{i\leq j\leq k}\{dis[i]+dis[k]-2*dis[j]\}\)

维护区间最大值,区间最小值,\(dis[i]-2*dis[j]\) 的最大值,\(dis[k]-2*dis[j]\) 的最大值,以及区间的答案。

修改边权相当于在子树区间加,直接用线段树维护就可以了。


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=200011; typedef long long lll;
struct node{int y; lll w; int next;}e[N];
int dfn[N],nfd[N],as[N],n,et=1,m,tot,rfn[N];
lll lim,lans,dis[N],w[N<<2],lazy[N<<2],lmx[N<<2],rmx[N<<2],mx[N<<2],mn[N<<2];
lll iut(){
	lll ans=0,f=1; char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans*f;
}
void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
lll min(lll a,lll b){return a<b?a:b;}
lll max(lll a,lll b){return a>b?a:b;}
void dfs(int x,int fa){
	nfd[dfn[x]=++tot]=x;
	for (int i=as[x];i;i=e[i].next)
	if (e[i].y!=fa){
		dis[e[i].y]=dis[x]+e[i].w,
		dfs(e[i].y,x),nfd[++tot]=x;
	}
	rfn[x]=tot;
}
void pup(int k){
	mn[k]=min(mn[k<<1],mn[k<<1|1]),mx[k]=max(mx[k<<1],mx[k<<1|1]);
	lmx[k]=max(max(lmx[k<<1],lmx[k<<1|1]),mx[k<<1]-2*mn[k<<1|1]);
    rmx[k]=max(max(rmx[k<<1],rmx[k<<1|1]),mx[k<<1|1]-2*mn[k<<1]);
    w[k]=max(max(w[k<<1],w[k<<1|1]),max(lmx[k<<1]+mx[k<<1|1],mx[k<<1]+rmx[k<<1|1]));
}
void build(int k,int l,int r){
	if (l==r){
		mn[k]=mx[k]=dis[nfd[l]],
		lmx[k]=rmx[k]=-dis[nfd[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pup(k);
}
void ptag(int k,lll z){mn[k]+=z,mx[k]+=z,lmx[k]-=z,rmx[k]-=z,lazy[k]+=z;}
void update(int k,int l,int r,int x,int y,lll z){
	if (l==x&&r==y){
		ptag(k,z);
		return;
	}
	int mid=(l+r)>>1;
	if (lazy[k]){
		ptag(k<<1,lazy[k]);
		ptag(k<<1|1,lazy[k]);
		lazy[k]=0;
	}
	if (y<=mid) update(k<<1,l,mid,x,y,z);
	else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
	    else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
	pup(k);
}
int main(){
	n=iut(),m=iut(),lim=iut();
	for (int i=1;i<n;++i){
		int x=iut(),y=iut(); lll w=iut();
		e[++et]=(node){y,w,as[x]},as[x]=et;
		e[++et]=(node){x,w,as[y]},as[y]=et;
	}
	dfs(1,0),build(1,1,tot);
	for (int i=1;i<=m;++i){
		int o=(iut()+lans)%(n-1)+1; lll W=(iut()+lans)%lim;
		int x=e[o<<1].y,y=e[o<<1|1].y;
		if (dis[x]<dis[y]) x^=y,y^=x,x^=y;
		update(1,1,tot,dfn[x],rfn[x],W-e[o<<1].w);
		e[o<<1].w=e[o<<1|1].w=W,print(lans=w[1]),putchar(10);
	}
	return 0;
}
posted @ 2022-03-22 20:58  lemondinosaur  阅读(61)  评论(0编辑  收藏  举报