並不對勁的bzoj5341:[Ctsc2018]暴力寫掛
阿新 • • 發佈:2018-12-21
題目大意
有兩棵\(n\)(\(n\leq366666\))個節點的樹,\(T\)和\(T'\),有邊權
\(dep(i)\)表示在\(T\)中\(i\)號點到\(1\)號點的距離,\(dep'(i)\)表示在\(T'\)中\(i\)號點到\(1\)號點的距離
\(lca(i,j)\)表示在\(T\)中\(i\)號點到\(j\)號點的簡單路徑上到\(1\)號點邊數最少的點,\(lca'(i,j)\)表示在\(T'\)中\(i\)號點到\(j\)號點的簡單路徑上到\(1\)號點邊數最少的點
求\(max(dep(x)+dep(y)-dep(lca(x,y))-dep'(lca'(x,y)))\)
題解
\(dis(x,y)\)表示在\(T\)中\(x\)號點到\(y\)號點的距離
原式變為\(max(\frac{1}{2}*(dep(x)+dep(y)-dis(x,y))-dep'(lca'(x,y)))\)
列舉兩點在\(T'\)中的lca,那麼剩下的部分只和兩點在\(T\)中的深度、距離有關,與\(T\)中lca無關,將\(dep(x),dep(y)\)看成點權,\(T\)變為無根樹,可以進行點分治或邊分治,求出一對點在\(T\)中的距離加兩點點權的最大值。
也就是說,要先計算\(T'\)中某點前\(k-1\)棵子樹和該點第\(k\)棵子樹對答案的影響,然後再將第\(k\)棵子樹與前\(k-1\)
這個可以在點(邊)分樹在合併時計算
點分樹合併沒有複雜度保證;邊分樹長得像線段樹,合併時也可以類似線段樹合併
#include<algorithm> #include<cmath> #include<complex> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<iomanip> #include<iostream> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define rep(i,x,y) for(register int i=(x);i<=(y);++i) #define dwn(i,x,y) for(register int i=(x);i>=(y);--i) #define maxn 366670 #define maxn2 (maxn<<1) #define maxn4 (maxn<<2) #define LL long long #define mi (l+r>>1) #define ls(u) (son[u][0]) #define rs(u) (son[u][1]) using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)&&ch!='-')ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); return x*f; } void write(LL x) { if(x==0){putchar('0'),putchar('\n');return;} int f=0;char ch[20]; if(x<0)putchar('-'),x=-x; while(x)ch[++f]=x%10+'0',x/=10; while(f)putchar(ch[f--]); putchar('\n'); return; } struct edge{int nxt,v;int w;}e0[maxn2],e1[maxn2],e2[maxn4]; int n,siz[maxn2],vis[maxn4],cnt0,cnt1,cnt2,fir[maxn],fir1[maxn],fir2[maxn2],st[22][maxn4],lg[maxn4],tim,dfn[maxn2],dep[maxn2],wk,mnsz,nd,nowsiz; int to[maxn4*5],bac[maxn2],son[maxn4*22][2],rt[maxn2],cntnd; LL dep2[maxn2],len[maxn4*22],ans,maxm,inf[2]; void ade(int u1,int v1,int w1){e0[cnt0].v=v1,e0[cnt0].w=w1,e0[cnt0].nxt=fir[u1],fir[u1]=cnt0++;} void ade1(int u1,int v1,int w1){e1[cnt1].v=v1,e1[cnt1].w=w1,e1[cnt1].nxt=fir1[u1],fir1[u1]=cnt1++;} void ade2(int u1,int v1,int w1){e2[cnt2].v=v1,e2[cnt2].w=w1,e2[cnt2].nxt=fir2[u1],fir2[u1]=cnt2++;} void getsiz(int u,int fa) { siz[u]=1; for(int k=fir2[u];k!=-1;k=e2[k].nxt) if(e2[k].v!=fa&&!vis[k]&&!vis[k^1]) { getsiz(e2[k].v,u),siz[u]+=siz[e2[k].v]; if(max(siz[e2[k].v],nowsiz-siz[e2[k].v])<mnsz)mnsz=max(siz[e2[k].v],nowsiz-siz[e2[k].v]),wk=k; } } int Lca2(int x,int y) { x=dfn[x],y=dfn[y]; if(x>y)swap(x,y); return dep[st[lg[y-x+1]][x]]<dep[st[lg[y-x+1]][y-(1<<lg[y-x+1])+1]]?st[lg[y-x+1]][x]:st[lg[y-x+1]][y-(1<<lg[y-x+1])+1]; } inline LL dis2(int x,int y){return dep2[x]+dep2[y]-2ll*dep2[Lca2(x,y)];} void getwt(int now,int u) { if(nowsiz==1){to[u]=-now;bac[now]=u;return;} mnsz=nd+1; getsiz(now,0);int nowk=wk; to[u]=nowk; vis[nowk]=vis[nowk^1]=1; int siz1=siz[e2[nowk].v],siz2=siz[e2[nowk^1].v]; if(siz1>siz2)siz1=nowsiz-siz2; else siz2=nowsiz-siz1; nowsiz=siz1,getwt(e2[nowk].v,u<<1),nowsiz=siz2,getwt(e2[nowk^1].v,u<<1|1); } void get2(int u,int fa) { int f=0,lst; for(int k=fir[u];k!=-1;k=e0[k].nxt)if(e0[k].v!=fa)lst=e0[k].v; for(int k=fir[u];k!=-1;k=e0[k].nxt) if(e0[k].v!=fa) { if(!f)ade2(u,e0[k].v,e0[k].w),ade2(e0[k].v,u,e0[k].w),f=u; else { if(lst!=e0[k].v)nd++,ade2(f,nd,0),ade2(nd,f,0),ade2(nd,e0[k].v,e0[k].w),ade2(e0[k].v,nd,e0[k].w),f=nd; else ade2(f,e0[k].v,e0[k].w),ade2(e0[k].v,f,e0[k].w); } get2(e0[k].v,u); } } void getst(int u) { dfn[u]=++tim;st[0][tim]=u; for(int k=fir2[u];k!=-1;k=e2[k].nxt) if(!dfn[e2[k].v])dep2[e2[k].v]=dep2[u]+(LL)e2[k].w,dep[e2[k].v]=dep[u]+1,getst(e2[k].v),st[0][++tim]=u; } int getrt(int node) { int now=bac[node],u,lst=0,f; while(now) { u=++cntnd; if(lst)son[u][f]=lst; if(now>>1)len[u]=dis2(node,e2[to[(now>>1)]].v)+dep2[node]; f=0,lst=u; if((((now>>1)<<1)|1)==now)f=1; now>>=1; } return u; } void merge(int ua,int ub) { if(ls(ua)&&rs(ub))maxm=max(maxm,(len[ls(ua)]+len[rs(ub)])/2ll); if(rs(ua)&&ls(ub))maxm=max(maxm,(len[rs(ua)]+len[ls(ub)])/2ll); len[ua]=max(len[ua],len[ub]); if(ls(ub)) { if(ls(ua))merge(ls(ua),ls(ub)); else ls(ua)=ls(ub); } if(rs(ub)) { if(rs(ua))merge(rs(ua),rs(ub)); else rs(ua)=rs(ub); } return; } void getans(int u,int fa,LL nowdep) { rt[u]=getrt(u); for(int k=fir1[u];k!=-1;k=e1[k].nxt) if(e1[k].v!=fa)getans(e1[k].v,u,nowdep+e1[k].w); maxm=dep2[u]; for(int k=fir1[u];k!=-1;k=e1[k].nxt) if(e1[k].v!=fa)merge(rt[u],rt[e1[k].v]); ans=max(ans,maxm-nowdep); } int main() { memset(fir,-1,sizeof(fir)); memset(fir1,-1,sizeof(fir1)); memset(fir2,-1,sizeof(fir2)); memset(inf,0x7f,sizeof(inf)); n=nd=read(); rep(i,1,n-1){int x=read(),y=read(),z=read();ade(x,y,z),ade(y,x,z);} rep(i,1,n-1){int x=read(),y=read(),z=read();ade1(x,y,z),ade1(y,x,z);} get2(1,0); getst(1); lg[0]=-1; rep(i,1,tim)lg[i]=lg[i>>1]+1; rep(k,1,lg[tim])for(int i=1;i+(1<<k)-1<=tim;++i) st[k][i]=dep[st[k-1][i]]<dep[st[k-1][i+(1<<k-1)]]?st[k-1][i]:st[k-1][i+(1<<k-1)]; nowsiz=nd;ans=-inf[0]; getwt(1,1); getans(1,0,0); write(ans); return 0; }