[bzoj3991] [SDOI2015]寻宝游戏
显然每次走过的最小路程,就是按照dfs序走的总路程。
如果没修改的话其实是虚树。。
既然带了修改。。。其实就是维护关键点的dfs序。
用棵平衡树维护一下就好了,涉及到插入、删除、查找前驱后继、查找最大最小值。
算两点间路程还得求lca
(所以这题就变成treap全套板子了。。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=100233; 8 struct zs{int too,pre,dis;}e[maxn<<1];int tot,last[maxn]; 9 int lc[maxn<<1],rc[maxn<<1],p[maxn<<1],rnd[maxn<<1],tt,V,rt,PRE,AFT,st,ed; 10 int dep[maxn],bel[maxn],fa[maxn],sz[maxn],dfn[maxn],tim; 11 ll dis[maxn],ans; 12 int i,j,k,n,m,cnt; 13 bool is[maxn]; 14 15 int ra,fh;char rx; 16 inline int read(){ 17 rx=getchar(),ra=0,fh=1; 18 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 19 if(rx=='-')fh=-1,rx=getchar(); 20 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 21 } 22 23 inline void lturn(int &x){int R=rc[x];rc[x]=lc[R],lc[R]=x,x=R;} 24 inline void rturn(int &x){int L=lc[x];lc[x]=rc[L],rc[L]=x,x=L;} 25 void insert(int &x){ 26 if(!x){x=++tt,p[x]=V,rnd[x]=rand()+tt;return;} 27 if(dfn[V]<dfn[p[x]]){ 28 insert(lc[x]); 29 if(rnd[lc[x]]<rnd[x])rturn(x); 30 }else{ 31 insert(rc[x]); 32 if(rnd[rc[x]]<rnd[x])lturn(x); 33 } 34 } 35 void del(int &x){ 36 if(p[x]==V){ 37 if(!lc[x]||!rc[x])x=lc[x]|rc[x]; 38 else if(rnd[lc[x]]<rnd[rc[x]])rturn(x),del(x); 39 else lturn(x),del(x); 40 }else 41 if(dfn[V]<dfn[p[x]])del(lc[x]);else del(rc[x]); 42 } 43 void getpre(int x){ 44 if(!x)return; 45 if(dfn[p[x]]<dfn[V])PRE=p[x],getpre(rc[x]); 46 else getpre(lc[x]); 47 } 48 void getaft(int x){ 49 if(!x)return; 50 if(dfn[p[x]]>dfn[V])AFT=p[x],getaft(lc[x]); 51 else getaft(rc[x]); 52 } 53 inline void getst(){ 54 int x=rt; 55 while(lc[x])x=lc[x]; 56 st=p[x]; 57 } 58 inline void geted(){ 59 int x=rt; 60 while(rc[x])x=rc[x]; 61 ed=p[x]; 62 } 63 64 65 void dfs(int x){ 66 sz[x]=1,dep[x]=dep[fa[x]]+1; 67 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]) 68 fa[e[i].too]=x,dis[e[i].too]=dis[x]+e[i].dis,dfs(e[i].too),sz[x]+=sz[e[i].too]; 69 } 70 void dfs2(int x,int chain){ 71 int mx=0,i;dfn[x]=++tim,bel[x]=chain; 72 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&sz[e[i].too]>sz[mx])mx=e[i].too; 73 if(!mx)return; 74 dfs2(mx,chain); 75 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too); 76 } 77 inline int getlca(int a,int b){ 78 while(bel[a]!=bel[b]){ 79 if(dep[bel[a]]<dep[bel[b]])swap(a,b); 80 a=fa[bel[a]]; 81 } 82 return dep[a]<dep[b]?a:b; 83 } 84 inline ll getdis(int a,int b){ 85 int c=getlca(a,b); 86 return dis[b]-dis[c]+dis[a]-dis[c]; 87 } 88 inline void insert(int a,int b,int c){ 89 e[++tot].too=b,e[tot].dis=c,e[tot].pre=last[a],last[a]=tot, 90 e[++tot].too=a,e[tot].dis=c,e[tot].pre=last[b],last[b]=tot; 91 } 92 int main(){ 93 n=read(),m=read(); 94 for(i=1;i<n;i++)j=read(),k=read(),insert(j,k,read()); 95 dfs(1),dfs2(1,1); 96 while(m--){ 97 i=read(); 98 if(!is[i]){ 99 V=i,PRE=AFT=0,getpre(rt),getaft(rt); 100 if(PRE||AFT){ 101 if(!PRE)PRE=ed;if(!AFT)AFT=st; 102 ans=ans-getdis(PRE,AFT)+getdis(PRE,i)+getdis(i,AFT); 103 } 104 insert(rt),is[i]=1,cnt++; 105 }else{ 106 V=i,PRE=AFT=0,getpre(rt),getaft(rt); 107 if(PRE||AFT){ 108 if(!PRE)PRE=ed;if(!AFT)AFT=st; 109 ans=ans+getdis(PRE,AFT)-getdis(PRE,i)-getdis(i,AFT); 110 } 111 del(rt),is[i]=0,cnt--; 112 } 113 if(cnt)getst(),geted(); 114 printf("%lld\n",ans); 115 } 116 return 0; 117 }