题目大意:支持多次操作,增加或删除一个关键点

动态维护虚树边权和*2

分析:可以用树链求并的方法,最后减去虚树的根到1距离

注意到树链求并是所有点到根距离-所有dfn序相邻两点的LCA到根距离

找dfn左右两个点稍微求一下,那就平衡树维护咯

树总根是dfn最小的点和最大的点的LCA

=================================================

md智障想偷懒不写平衡树,写了个set,然后gg不会写搞了两个小时

=================================================

set定义+迭代器

set<int>S;
set<int>::iterator it;

set存储方式:

1.左闭右开

begin()是指向第一个点,end()指向最后一个点后的一个结束指针

2.特别的,set空时begin()==end()

3.不允许有重复元素

set小函数(方便使用)

int getnxt(int x){
    it=S.upper_bound(x);
    return it!=S.end() ? pid[*it] : -1;
}
int getpre(int x){
    it=S.lower_bound(x);
    return it!=S.begin() ? pid[*(--it)] : -1;
}
int getfirst(){
    it=S.begin();
    return it!=S.end() ? pid[*it] : -1;
}
int getlast(){
    it=S.end();
    return it!=S.begin() ? pid[*(--it)] : -1;
} 

本题代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <set>
using namespace std;
typedef long long LL;
const int M=100007;
inline int rd(){
    int x=0;bool f=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=0;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return f?x:-x;
}

int vis[M];
int n,m;
bool use[M];
int g[M],te;
struct edge{int y,next;LL d;}e[M<<1];
void addedge(int x,int y,LL d){
    e[++te].y=y;e[te].d=d;e[te].next=g[x];g[x]=te;
}
int dfn[M],pid[M],tdfn;
int a[M<<1][20],ln[M<<1],pos[M],T;
LL dis[M];

void dfs(int x,int fa){
    pid[dfn[x]=++tdfn]=x;
    a[pos[x]=++T][0]=x;
    int p,y;
    for(p=g[x];p;p=e[p].next)
    if((y=e[p].y)!=fa){
        dis[y]=dis[x]+e[p].d;
        dfs(y,x);
        a[++T][0]=x;
    }
}

set<int>S;
set<int>::iterator it;

int mn(int x,int y){return dfn[x]<dfn[y]?x:y;}

void init(){
    int i,j,l;
    for(i=2;i<=T;i++) ln[i]=ln[i>>1]+1;
    for(i=T;i>0;i--){
        l=ln[T-i+1];
        for(j=1;j<=l;j++) a[i][j]=mn(a[i][j-1],a[i+(1<<j-1)][j-1]);
    }
}

int LCA(int x,int y){
    x=pos[x],y=pos[y];
    int l=ln[y-x+1];
    return mn(a[x][l],a[y-(1<<l)+1][l]);
}

int getnxt(int x){
    it=S.upper_bound(x);
    return it!=S.end() ? pid[*it] : -1;
}

int getpre(int x){
    it=S.lower_bound(x);
    return it!=S.begin() ? pid[*(--it)] : -1;
}

int getfirst(){
    it=S.begin();
    return it!=S.end() ? pid[*it] : -1;
}

int getlast(){
    it=S.end();
    return it!=S.begin() ? pid[*(--it)] : -1;
} 

int main(){
    freopen("a.txt","r",stdin);
    int i,x,y,z,l,r;
    LL ans=0;
    n=rd(),m=rd();
    for(i=1;i<n;i++){
        x=rd(),y=rd(),z=rd();
        addedge(x,y,z);
        addedge(y,x,z);
    }
    dfs(1,0);
    init();
    for(i=1;i<=m;i++){
        x=rd();
        if(use[x]){
            S.erase(dfn[x]);
            l=getpre(dfn[x]);
            r=getnxt(dfn[x]);

            if(l!=-1&&r!=-1) ans-=dis[LCA(l,r)];
            if(l!=-1) ans+=dis[LCA(l,x)];
            if(r!=-1) ans+=dis[LCA(x,r)];
            ans-=dis[x];
        }
        else{
            l=getpre(dfn[x]);
            r=getnxt(dfn[x]);
            S.insert(dfn[x]);

            if(l!=-1&&r!=-1) ans+=dis[LCA(l,r)];
            if(l!=-1) ans-=dis[LCA(l,x)];
            if(r!=-1) ans-=dis[LCA(x,r)];
            ans+=dis[x];
        }
        use[x]^=1;

        it=S.begin();
        if(it==S.end()) puts("");
        else{
            l=getfirst();
            r=getlast();
            printf("%lld\n",(ans-dis[LCA(l,r)])*2);
        }
    }
    return 0;
}

bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并的更多相关文章

  1. [BZOJ3991][SDOI2015]寻宝游戏

    [BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...

  2. CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏

    异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...

  3. bzoj3991 [SDOI2015]寻宝游戏 树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...

  4. [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set

    寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...

  5. BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】

    题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...

  6. bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护

    之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...

  7. 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏

    在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...

  8. bzoj 3991: [SDOI2015]寻宝游戏 虚树 set

    目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...

  9. 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set

    [BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...

随机推荐

  1. POJ2718 递归套递归

    就是给你一个数,排列组合,然后问如何排列之间的差值最小. 我之前的想法是一个递归,然后两个for循环枚举L1和L2,结果TLE了,然后想了一下剪枝发现没办法剪,然后看了一下别人的代码,用了next_p ...

  2. 操,escape sequence的输入方法我以前找过一次,这次又忘了,又找了一次,记下来,

    所有的手册和回答都没有说,都是用 echo -e '\e[22;22m,如果不愿意使用echo -e,也可以 输入CvC[[22:22m 不要再忘记了.

  3. 关于java.lang.reflect.InvocationTargetException(jar 包缺少或者冲突)的错误

    我在合肥那边运行了的是湖北石首市的项目没有错 可是回武汉之后 运行这个项目 点击这里的时候 就报错java.lang.reflect.InvocationTargetException   不是数据库 ...

  4. gen_grant_dml.sql

    set echo off feedback off verify off pagesize 0 linesize 120 define v_grantee                = & ...

  5. python+mysql抓取百度新闻的标题存到数据库

    #!usr/bin/python# -*- coding:utf-8 -*-import urllib2 import re import MySQLdb class BaiDuNews: def _ ...

  6. map遍历的四种方式

    原文 http://blog.csdn.net/dayanxuqun/article/details/26348277 以下是map遍历的四种方式: // 一.推荐只用value的时候用,都懂的... ...

  7. (转)Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区别

    Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区别 ava.io下面有两个抽象类:InputStream和 ...

  8. OCR图片识别引擎

    OCR引擎 OCR(Optical Character Recognition)是指使用扫描仪或数码相机对文本资料进行扫描成图像文件,然后对图像文件进行分析处理,自动识别获取文字信息及版面信息的软件. ...

  9. java获取硬盘ID以及MAC地址

    http://blog.csdn.net/coolwzjcool/article/details/6698327 版权声明:本文为博主原创文章,未经博主允许不得转载. 为了达到软件注册,或者说软件和电 ...

  10. python之路:进阶篇 内置函数

     li = [11, 22, 33] news = map(  li = [100, 2200, 3300] news = map(  [13, 24, 35] [11, 11, 11] [22, 4 ...