[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 }
View Code

 

posted @ 2016-06-18 15:39  czllgzmzl  阅读(221)  评论(0编辑  收藏  举报