zoukankan      html  css  js  c++  java
  • P6845 [CEOI2019] Dynamic Diameter

    P6845 [CEOI2019] Dynamic Diameter

    题意

    一颗带权树,每次更改一条边的权,每次修改后求出最大直径。强制在线。

    思路

    (O(nlog^2n)) 的暴力做法。

    根据经典结论,对于两个点集的树上最大直径(权值非负),并集点集的树上最大直径的端点一定是原四个端点中的两个。

    那么我们就可以用线段树维护点集,合并时 (O(log n)) 查询两点间距离合并就可以做到 (O(nlog^2n)) 的复杂度了。

    思考如何支持在线修改边权。两点间距离为 (dis(x)+dis(y)-2*dis(lca(x,y))) 那么先树剖发现修改一条边的权实际上是将子树内 (dis) 增加,那么子树就是区间加。我们可以用树状数组维护修改。

    考虑哪些部分的线段树上的点集最大直径被改了。发现子树内和子树外的最大直径不会变化,那么我们只需要更改子树内与外之间合并的最大直径就行了。我们按照 (dfn) 用线段树进行维护,那么我们每次只需要将子树区间重新 pushup 一下就可以了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    #include<cstdlib>
    #include<utility>
    using namespace std;
    inline long long read(){
    	long long x=0;int w=0;char c=getchar();
    	while(!isdigit(c)) w|=c=='-',c=getchar();
    	while(isdigit(c)) x=x*10+(c^48),c=getchar();
    	return w?-x:x;
    }
    namespace star
    {
    	const int maxn=1e5+10;
    	int n,q;
    	int ecnt=1,head[maxn],to[maxn<<1],nxt[maxn<<1],go[maxn];
    	long long W,w[maxn],dis[maxn];
    	inline void addedge(){
    		int a=read(),b=read();
    		to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt;
    		to[++ecnt]=a,nxt[ecnt]=head[b],head[b]=ecnt;
    		w[ecnt>>1]=read();
    	}
    	int dep[maxn],fa[maxn],top[maxn],siz[maxn],son[maxn],dfn[maxn],id[maxn];
    	void dfs1(int x,int f){
    		fa[x]=f,dep[x]=dep[f]+1,siz[x]=1;
    		for(int u,i=head[x];i;i=nxt[i]) if((u=to[i])!=f){
    			dis[u]=dis[x]+w[i>>1],dfs1(u,x),go[i>>1]=u;
    			if(siz[u]>siz[son[x]]) son[x]=u;
    			siz[x]+=siz[u];
    		}
    	}
    	void dfs2(int x,int topf){
    		top[x]=topf,dfn[x]=++dfn[0],id[dfn[0]]=x;
    		if(!son[x]) return;
    		dfs2(son[x],topf);
    		for(int u,i=head[x];i;i=nxt[i]) if((u=to[i])!=fa[x] and u!=son[x]) dfs2(u,u);
    	}
    	inline int LCA(int x,int y){
    		while(top[x]!=top[y]) dep[top[x]]>dep[top[y]]?(x=fa[top[x]]):(y=fa[top[y]]);
    		return dep[x]<dep[y]?x:y;
    	}
    	#define ls (ro<<1)
    	#define rs (ro<<1|1)
    	#define mid ((l+r)>>1)
    	namespace S{
    		long long c[maxn];
    		inline void upd(int x,long long k){for(;x<=n;x+=x&-x) c[x]+=k;}
    		inline long long query(int x){long long ans=dis[id[x]];for(;x;x-=x&-x) ans+=c[x];return ans;}
    		inline void update(int x,int y,long long w){upd(x,w),upd(y+1,-w);}
    	}
    	inline long long Dis(pair<int,int> a){return S::query(dfn[a.first])+S::query(dfn[a.second])-2*S::query(dfn[LCA(a.first,a.second)]);}
    	namespace T{
    		pair<int,int> e[maxn<<2];
    		inline pair<int,int> merge(const pair<int,int>& a,const pair<int,int>& b){
    			pair<int,int> p[6]={a,b,make_pair(a.first,b.first),make_pair(a.first,b.second),make_pair(a.second,b.first),make_pair(a.second,b.second)};
    			long long dis[6];
    			for(int i=0;i<6;i++) dis[i]=Dis(p[i]);
    			return p[max_element(dis,dis+6)-dis];
    		}
    		void build(int ro=1,int l=1,int r=n){
    			if(l==r) return e[ro]=make_pair(id[l],id[l]),void();
    			build(ls,l,mid),build(rs,mid+1,r);
    			e[ro]=merge(e[ls],e[rs]);
    		}
    		void update(int x,int y,int ro=1,int l=1,int r=n){
    			if(x==l and y==r) return;
    			if(y<=mid) update(x,y,ls,l,mid);
    			else if(x>mid) update(x,y,rs,mid+1,r);
    			else update(x,mid,ls,l,mid),update(mid+1,y,rs,mid+1,r);
    			e[ro]=merge(e[ls],e[rs]);
    		}
    	}
    	#undef ls
    	#undef rs
    	#undef mid
    	inline void work(){
    		n=read(),q=read(),W=read();
    		for(int i=1;i<n;i++) addedge();	
    		dfs1(1,0),dfs2(1,1);
    		T::build();
    		long long ans=0;
    		while(q--){
    			int e=(read()+ans)%(n-1)+1;
    			long long v=(read()+ans)%W;
    			S::update(dfn[go[e]],dfn[go[e]]+siz[go[e]]-1,v-w[e]),w[e]=v;
    			T::update(dfn[go[e]],dfn[go[e]]+siz[go[e]]-1);
    			printf("%lld
    ",ans=Dis(T::e[1]));
    		}
    	}
    }
    signed main(){
    	star::work();
    	return 0;
    }
    
  • 相关阅读:
    mybatis设置select返回HashMap,字段值为null时,不会保存key
    copyProperties 忽略null值字段
    动态新增表单
    页面时时刷新数据
    FormData 传List对象集合到后台
    linux常用命令总结
    Linux部署安装JDK
    yum安装nginx
    01_Python基础
    Nginx防盗链
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/14694283.html
Copyright © 2011-2022 走看看