• bzoj3991 [SDOI2015]寻宝游戏


    虚树,一直在想怎么在虚树里快速插入一个节点,其实不需要。

    考虑我们要求的是什么,是按dfs序排序后的相邻关键点的距离和,于是我们直接用一个set维护当前的关键点集合,并记录当前的答案,有修改就在set里插入或删除就好了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <set>
     7 #define N 100500
     8 using namespace std;
     9 int e=1,head[N];
    10 struct edge{
    11     int v,w,next;
    12 }ed[N<<1];
    13 int dep[N],fa[N][22],L[N],tot,n,m;
    14 bool vis[N];
    15 long long val[N];
    16 struct cmp{
    17     bool operator () (int a,int b){
    18         return L[a]<L[b];
    19     }
    20 };
    21 set<int ,cmp> s;
    22 set<int ,cmp> :: iterator it;
    23 void push(int u,int v,int w){
    24     ed[e].v=v;ed[e].w=w;
    25     ed[e].next=head[u];head[u]=e++;
    26 }
    27 void dfs(int x,int d){
    28     dep[x]=d;L[x]=++tot;
    29     for(int i=1;(1<<i)<=d;i++)
    30         fa[x][i]=fa[fa[x][i-1]][i-1];
    31     for(int i=head[x];i;i=ed[i].next){
    32         int v=ed[i].v;
    33         if(v==fa[x][0])continue;
    34         fa[v][0]=x;val[v]=val[x]+ed[i].w;
    35         dfs(v,d+1);
    36     }
    37 }
    38 int getlca(int x,int y){
    39     if(dep[x]<dep[y])swap(x,y);
    40     for(int i=20;~i;i--)
    41         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
    42     if(x==y)return x;
    43     for(int i=20;~i;i--)
    44         if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    45     return fa[x][0];
    46 }
    47 long long getdis(int x,int y){
    48     return val[x]+val[y]-2*val[getlca(x,y)];
    49 }
    50 int size;
    51 long long sum;
    52 void work(int x,int v){
    53     int y,z;
    54     it=s.find(x);
    55     if(it!=s.begin())it--,y=*it;
    56     else it=s.end(),it--,y=*it;
    57     it=s.find(x);it++;
    58     if(it!=s.end())z=*it;
    59     else it=s.begin(),z=*it;
    60     sum+=v*(getdis(x,y)+getdis(x,z)-getdis(y,z));
    61 }
    62 void del(int x){
    63     size--;vis[x]=0;
    64     if(size<2)sum=0;
    65     else work(x,-1);
    66     s.erase(x);
    67 }
    68 void add(int x){
    69     size++;vis[x]=1;
    70     s.insert(x);
    71     if(size<2)sum=0;
    72     else work(x,1);
    73 }
    74 int main(){
    75     scanf("%d%d",&n,&m);
    76     for(int i=1,u,v,w;i<n;i++){
    77         scanf("%d%d%d",&u,&v,&w);
    78         push(u,v,w); push(v,u,w);
    79     }
    80     dfs(1,1);
    81     int x;
    82     while(m--){
    83         scanf("%d",&x);
    84         if(vis[x]) del(x);
    85         else add(x);
    86         printf("%lld
    ",sum);
    87     }
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    iOS开发基础-UITableView基本属性
    iOS开发基础-UITableView控件简单介绍
    iOS开发基础-UIScrollView实现图片缩放
    iOS开发基础-UIScrollView基础
    iOS开发基础-序列帧动画之Tom猫
    iOS开发基础-KVC简单介绍
    iOS开发基础-九宫格坐标(6)
    iOS开发基础-九宫格坐标(5)
    iOS开发基础-九宫格坐标(4)
    iOS开发基础-九宫格坐标(3)之Xib
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8568103.html
Copyright © 2020-2023  润新知