<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12


      UOJ#400. 【CTSC2018】暴力寫掛 邊分治 線段樹合并

      原文鏈接 www.rzrgm.cn/zhouzhendong/p/UOJ400.html

      前言

      老年選手沒有碼力。

      題解

      先對第一棵樹進行邊分治,然后,設點 x 到分治中心的距離為 $D[x]$,點 x 在原樹上的深度為 $d[x]$,那么

      $$d[x]+d[y] - d[LCA(x,y)] - d'[LCA(x,y)] = \frac 12(D[x] + d[x]) + \frac 12 (D[y] + d[y]) - d'[LCA(x,y)]$$

      于是我們考慮將分治區域內的節點在第二棵樹上建虛樹,并 DFS,每次維護一下子樹中的 max(D[x] + d[x]) ,合并到父親時順便算一下答案。

      類似于WC2018通道,這樣做的時間復雜度是可以強行優化成 $O(n\log n)$ 的。

       

      但是本題有更巧妙的做法。

       

      考慮邊分樹這個數據結構。它具有幾個性質:

      1. 深度為 $O(\log n)$,準確地說是略大于 $\log _2 n $ 的,約等于 $\log_{1.5} n$。(嗯對,xza深度只開了20,被我hack了\kel)

      2. 葉子節點個數為 $n$ 。

      如果任取一種 DFS 序,并將其葉子按順序排列,那么,兩組節點的邊分樹合并的過程就可以看做以葉子 DFS 序為定義域的線段樹合并。時間復雜度證明和線段樹合并相同。寫法也幾乎相同。

      于是,我們得到下面的優秀算法:

      首先對第一棵樹進行邊分治,建出邊分樹。

      然后對第二棵樹進行 DFS,用“邊分樹合并”來支持子樹合并操作。在邊分樹合并的同時計算答案。 我們要維護的值僅僅是邊分時兩半集合中節點的權值 max 。

      時間復雜度 $O(n\log n)$ 。

      代碼

      #include <bits/stdc++.h>
      #define clr(x) memset(x,0,sizeof (x))
      #define For(i,a,b) for (int i=a;i<=b;i++)
      using namespace std;
      typedef long long LL;
      LL read(){
      	LL x=0,f=0;
      	char ch=getchar();
      	while (!isdigit(ch))
      		f|=ch=='-',ch=getchar();
      	while (isdigit(ch))
      		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
      	return f?-x:x;
      }
      const int N=366677*2,S=N*13;
      const LL LLINF=1e18;
      struct Graph{
      	static const int M=N*2;
      	int cnt,y[M],fst[N],nxt[M],z[M];
      	void clear(){
      		cnt=1,clr(fst);
      	}
      	void add(int a,int b,int c){
      		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt,z[cnt]=c;
      	}
      	void Add(int a,int b,int c){
      		add(a,b,c),add(b,a,c);
      	}
      }t1,t2,T1;
      #define Forg(g) for (int E=g.fst[x],y=g.y[E];E;E=g.nxt[E],y=g.y[E]) if (y!=pre)
      int n,vcnt,ec;
      int td[N],vis[N],pos[N];
      LL d[N],val[27][N];
      void GetT1(int x,int pre,LL D){
      	int t=x,v;
      	d[x]=D;
      	Forg(t1)
      		d[v=++vcnt]=D,T1.Add(t,v,0),T1.Add(v,y,t1.z[E]),t=v,GetT1(y,x,D+t1.z[E]);
      }
      namespace DT{
      	int size[N],Mx[N],nowsize,kx,ky,kz;
      	void GetRT(int x,int pre,int flen){
      		size[x]=1;
      		Forg(T1)
      			if (!vis[y])
      				GetRT(y,x,T1.z[E]),size[x]+=size[y];
      		Mx[x]=max(size[x],nowsize-size[x]);
      		if (!kx||Mx[x]<Mx[kx])
      			kx=x,ky=pre,kz=flen;
      	}
      	void dfs(int x,int pre,LL D,int w){
      		pos[x]|=w<<td[x],val[td[x]++][x]=D+d[x];
      		Forg(T1)
      			if (!vis[y])
      				dfs(y,x,D+T1.z[E],w);
      	}
      	void Divide(int x,int Size){
      		if (Size>1){
      			kx=0,nowsize=Size,GetRT(x,0,0),x=kx;
      			int y=ky,z=kz,tmp=size[x];
      			dfs(x,y,0,0),dfs(y,x,z,1);
      			vis[y]=1,Divide(x,tmp),vis[y]=0;
      			vis[x]=1,Divide(y,Size-tmp);
      		}
      	}
      }
      int rt[N],ls[S],rs[S];
      LL Lmx[S],Rmx[S],ans=-LLINF;
      int st[S],top,cnt=0;
      int NewNode(){
      	return top?st[top--]:++cnt;
      }
      void RecNode(int x){
      	ls[x]=rs[x]=Lmx[x]=Rmx[x]=0,st[++top]=x;
      }
      void Ins(int &rt,int x,int D){
      	if (D<td[x]){
      		rt=NewNode(),Lmx[rt]=Rmx[rt]=-LLINF;
      		if (pos[x]>>D&1)
      			Ins(rs[rt],x,D+1),Rmx[rt]=max(Rmx[rt],val[D][x]);
      		else
      			Ins(ls[rt],x,D+1),Lmx[rt]=max(Lmx[rt],val[D][x]);
      	}
      }
      int Merge(int x,int y,LL add){
      	if (!x||!y)
      		return x|y;
      	ans=max(ans,max(Lmx[x]+Rmx[y],Rmx[x]+Lmx[y])/2+add);
      	Lmx[x]=max(Lmx[x],Lmx[y]),Rmx[x]=max(Rmx[x],Rmx[y]);
      	ls[x]=Merge(ls[x],ls[y],add),rs[x]=Merge(rs[x],rs[y],add);
      	return RecNode(y),x;
      }
      void Solve(int x,int pre,LL D){
      	ans=max(ans,d[x]-D),Ins(rt[x],x,0);
      	Forg(t2)
      		Solve(y,x,D+t2.z[E]),rt[x]=Merge(rt[x],rt[y],-D);
      }
      int main(){
      	n=read(),t1.clear(),t2.clear(),T1.clear();
      	For(i,1,n-1){
      		int x=read(),y=read(),z=read();
      		t1.Add(x,y,z);
      	}
      	For(i,1,n-1){
      		int x=read(),y=read(),z=read();
      		t2.Add(x,y,z);
      	}
      	vcnt=ec=n,GetT1(1,0,0),DT::Divide(1,vcnt),Solve(1,0,0);
      	cout<<ans<<endl;
      	return 0;
      }
      

        

      posted @ 2019-05-02 19:45  zzd233  閱讀(475)  評論(2)    收藏  舉報

      主站蜘蛛池模板: 欧美日产国产精品| 四虎国产精品永久入口| 欧美粗大猛烈老熟妇| 亚洲精品成人久久久| 亚洲国产天堂久久综合226114| 国产二区三区不卡免费| 中文字幕结果国产精品| 国产成人无码一二三区视频| 国产成人精品午夜福利在线观看| 蜜臀在线播放一区在线播放| 国产精品一区二区三区自拍| 国内少妇人妻偷人精品视频| 午夜福利国产盗摄久久性| 午夜高清福利在线观看| 欧美日韩中文国产一区| 日韩熟妇| 国产成人亚洲综合图区| 国产精品一二三区蜜臀av| 亚洲国产精品一二三四区| 国产白丝jk捆绑束缚调教视频| 日本欧洲亚洲高清在线| 国产又色又刺激高潮视频| 国产偷窥熟女精品视频大全| 大陆精大陆国产国语精品| 美女内射毛片在线看免费人动物| 国产精品大片中文字幕| 在线免费观看毛片av| 国产欧美日韩亚洲一区二区三区| 99久久亚洲综合精品成人网| av无码av无码专区| 四虎影视一区二区精品| 莱州市| 国产精品久久久久影院色| 久久久久无码中| 久久日产一线二线三线| caoporn成人免费公开| 武功县| 欧洲码亚洲码的区别入口| 毛片av在线尤物一区二区| 国产av日韩精品一区二区| 日本怡春院一区二区三区|