专出神题的xyz。
支持删加边、修改点权、维护树的直径。
LCT 需要额外记录子树信息。用一个堆维护。
#include<cstdio> #include<cstring> #include<algorithm> #include<set> #include<vector> #include<queue> using namespace std; #define rep(i,x,y) for(i=x;i<=y;i++) #define _rep(i,x,y) for(i=x;i>=y;i--) #define REP(i,x,y) for(int i=(x);i<=(y);i++) #define ALL(x,S) for(x=S.begin();x!=S.end();x++) #define mp make_pair #define fi first #define se second #define pb push_back template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c==‘-‘)fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-‘0‘;if(fu)x=-x;}; template<class T> inline void read(T&x,T&y){read(x);read(y);} template<class T> inline void read(T&x,T&y,T&z){read(x);read(y);read(z);} inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;} typedef long long ll; typedef pair<int,int> pii; int max(int a,int b,int c){return max(max(a,b),c);} const int N=100010; const int inf=int(1e9); int n,m,i,j,k,x,y,u,v,w0,w1; multiset<int> son[N],AN; multiset<int>::iterator pos; priority_queue<pii> Q; int ch[N][2],fa[N],key[N];bool rev[N]; int lw[N],rw[N],ans[N],len[N]; void Hins(int i,int t){son[i].insert(lw[t]);} void Hdel(int i,int t){son[i].erase(son[i].find(lw[t]));} int mson(int i){return son[i].empty()?0:*son[i].rbegin();} int tson(int i){if(son[i].size()<=1)return mson(i);pos=--son[i].end();return *pos+*(--pos);} bool tp(int i){return !(ch[fa[i]][0]==i||ch[fa[i]][1]==i);} void REV(int i){if(i){rev[i]=!rev[i];swap(ch[i][0],ch[i][1]);swap(lw[i],rw[i]);}} void D(int i){if(rev[i])rev[i]=0,REV(ch[i][0]),REV(ch[i][1]);} void U(int i) { #define L ch[i][0] #define R ch[i][1] len[i]=len[L]+key[i]+len[R]; ans[i]=max(rw[L]+lw[R],max(rw[L],lw[R])+mson(i),tson(i))+key[i]; lw[i]=max(lw[L],len[L]+key[i]+mson(i),len[L]+key[i]+lw[R]); rw[i]=max(rw[R],len[R]+key[i]+mson(i),len[R]+key[i]+rw[L]); Q.push(mp(ans[i],i)); } void rot(int i,int t){int x,y;x=ch[i][!t];D(x);y=ch[x][t];ch[i][!t]=y;ch[x][t]=i;if(y)fa[y]=i;if(fa[i])if(ch[fa[i]][0]==i)ch[fa[i]][0]=x;else if(ch[fa[i]][1]==i)ch[fa[i]][1]=x;fa[x]=fa[i];fa[i]=x;U(i);} void spl(int x){int y,z;D(x);while(!tp(x)){y=fa[x];z=fa[y];if(z)D(z);if(y)D(y);if(tp(y))rot(y,ch[y][0]==x);else if(ch[z][0]==y)if(ch[y][0]==x)rot(z,1),rot(y,1);else rot(y,0),rot(z,1);else if(ch[y][0]==x)rot(y,1),rot(z,0);else rot(z,0),rot(y,0);U(x);}} void acc(int x){for(int i=0,t;x;i=x,x=fa[x]){spl(x);t=ch[x][1];if(t)Hins(x,t);ch[x][1]=i;if(i){fa[i]=x;Hdel(x,i);}U(x);}} void maker(int x){acc(x);spl(x);REV(x);} void change(int x,int y){acc(x);spl(x);key[x]=y;U(x);} void cut(int x,int y){maker(x);acc(y);spl(y);ch[y][0]=0;fa[x]=0;U(y);} void link(int x,int y){maker(x);acc(y);spl(y);fa[x]=y;Hins(y,x);U(y);} vector<int> E[N];void dfs(int i){vector<int>::iterator it;ALL(it,E[i])if((*it)!=fa[i])fa[*it]=i,dfs(*it),Hins(i,*it);U(i);} void solve(){pii u;while(1){u=Q.top();if(ans[u.se]==u.fi)break;Q.pop();}printf("%d\n",u.fi);} int main() { freopen("longest.in","r",stdin);freopen("longest.out","w",stdout); read(n,m); rep(i,1,n-1)read(x,y),E[x].pb(y),E[y].pb(x); rep(i,1,n)read(key[i]); dfs(1); solve(); for(;m;m--) { char c=getc(); if(c==‘M‘)read(x,y),change(x,y); else if(c==‘C‘)read(x,y),read(u,v),cut(x,y),link(u,v); solve(); } return 0; }
[xyz模拟题]动态维护树的直径,布布扣,bubuko.com
原文:http://www.cnblogs.com/oldmanren/p/3730866.html