zoukankan      html  css  js  c++  java
  • loj 10132 异象石

    题目

    传送门:loj10132

    在 Adera 的异时空中有一张地图。这张地图上有 N 个点,有N-1  条双向边把它们连通起来。起初地图上没有任何异象石,在接下来的 M 个时刻中,每个时刻会发生以下三种类型的事件之一:

    1. 地图的某个点上出现了异象石(已经出现的不会再次出现);
    2. 地图某个点上的异象石被摧毁(不会摧毁没有异象石的点);
    3. 向玩家询问使所有异象石所在的点连通的边集的总长度最小是多少。

    请你作为玩家回答这些问题。下图是一个例子,灰色节点表示出现了异象石,加粗的边表示被选为连通异象石的边集。

    输入格式

    第一行有一个整数 N,表示点的个数;

    接下来 N-1 行每行三个整数 x,y,z,表示点 x 和 y 之间有一条长度为 z 的双向边;

    第 N+1 行有一个正整数 M

    接下来 M 行每行是一个事件,事件是以下三种格式之一:

    • + x:表示点 x 上出现了异象石;
    • - x:表示点 x 上的异象石被摧毁;
    • ?:表示询问使当前所有异象石所在的点连通所需的边集的总长度最小是多少。

    输出格式

    对于每个 ? 事件,输出一个整数表示答案。

    样例

    样例输入

    6 
    1 2 1 
    1 3 5 
    4 1 7 
    4 5 3 
    6 4 2 
    10 
    + 3 
    + 1 
    ? 
    + 6 
    ? 
    + 5 
    ? 
    - 6 
    - 3 
    ? 
    

    样例输出

    5 
    14 
    17 
    10 
    

    数据范围与提示

    对于100%的数据,1 ≤ n, m ≤ 105, 1 ≤ x, y ≤ n, x ≠ y, 1 ≤ z ≤ 109

    分析

    发现按dfs序排有异象石的点,算出相邻两点的距离的和,加上末尾与首位的距离,便是边和的两倍

    动态删除插入,平衡树,可以借助STL

    前置知识:

    STL平衡树:「LuoguP3369」 【模板】普通平衡树 (用vector乱搞平衡树   By qwerta

    STL set:【C++ STL】Set和Multiset

    STL迭代器:C++迭代器的使用和操作总结     C++ 迭代器运算

     

    代码

      1 /*************************
      2 User:Mandy.H.Y
      3 Language:
      4 Algorithm:
      5 Score:
      6 *************************/
      7 
      8 //动态插入删除,平衡树,
      9 //算了,用set  ^v^
     10 //还可以用multiset,vactor
     11 //都练练啦  
     12 
     13 #include<bits/stdc++.h>
     14 
     15 using namespace std;
     16 
     17 const int maxn = 1e5 + 5;
     18 
     19 int n,m,dfn[maxn],tot,last,rev[maxn];
     20 int size,first[maxn];
     21 long long dis[maxn];
     22 long long ans;//long long
     23 int father[maxn],top[maxn],cnt[maxn],dep[maxn];
     24 set<int>s;
     25 
     26 struct Edge{
     27     int v,nt,w;
     28 }edge[maxn << 1];
     29 
     30 template<class T>inline void read(T &x){
     31     x = 0;bool flag = 0;char ch = getchar();
     32     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
     33     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
     34     if(flag)x = -x;
     35 }
     36 
     37 template<class T>void putch(const T x){
     38     if(x > 9) putch(x / 10);
     39     putchar(x % 10 | 48);
     40 }
     41 
     42 template<class T>void put(const T x){
     43     if(x < 0) putchar('-'),putch(-x);
     44     else putch(x); 
     45 }
     46 
     47 void file(){
     48     freopen("10132.in","r",stdin);
     49 //    freopen("10132.out","w",stdout);
     50 }
     51 
     52 void eadd(int u,int v,int w){
     53     edge[ ++ size].v = v;
     54     edge[size].w = w;
     55     edge[size].nt = first[u];
     56     first[u] = size;
     57 }
     58 
     59 void readdata(){
     60     
     61     read(n);
     62     
     63     for(int i = 1;i < n;i ++ ){
     64         int u,v,w;
     65         read(u);read(v);read(w);
     66         eadd(u,v,w);eadd(v,u,w);
     67     }
     68     
     69     read(m);
     70 }
     71 
     72 void dfs(int u,int f,int d){
     73     
     74     dfn[u] = ++tot;rev[tot] = u;
     75     father[u] = f;dep[u] = d;
     76     top[u] = u;cnt[u] = 1;
     77     int mcnt = 0,son = 0;
     78     
     79     for(int i = first[u];i;i = edge[i].nt){
     80         int v = edge[i].v;
     81         int w = edge[i].w;
     82         if(v == f) continue;
     83         dis[v] = dis[u] + w;
     84         dfs(v,u,d + 1);
     85         cnt[u] += cnt[v];
     86         if(mcnt < cnt[v]){
     87             mcnt = cnt[v];
     88             son = v;
     89         }
     90     }
     91     
     92     if(son) top[son] = u;
     93     
     94 }
     95 
     96 int find(int x){
     97     return top[x] == x ? x : top[x] = find(top[x]);
     98 }
     99 
    100 int LCA(int x,int y){
    101     if(find(x) == find(y)) return dep[x] < dep[y] ? x : y;
    102     else return dep[top[x]] < dep[top[y]] ? LCA(x,father[top[y]]) : LCA(y,father[top[x]]);
    103     //又打错模板 
    104 }
    105 
    106 inline set<int>::iterator Left(set<int>::iterator u){
    107     set<int>::iterator l;
    108     if(u == s.begin()) l = --s.end();
    109     else l = --u;
    110     return l;
    111 } 
    112 
    113 inline set<int>::iterator Right(set<int>::iterator u){
    114     set<int>::iterator r;
    115     if(u == --s.end()) r = s.begin();
    116     else r = ++u;
    117     return r;
    118 } //还是打包比较稳妥 
    119 void work(){
    120     
    121     dfs(1,0,1);
    122     
    123     while(m -- ){
    124         char opt = getchar();
    125         int x;
    126         while(opt != '+' && opt != '-' && opt != '?') opt = getchar();
    127         switch(opt){
    128             
    129             case '+':{
    130                 read(x);
    131                 
    132                 if(s.size()){//判空 
    133                     
    134                     set<int> :: iterator u = s.lower_bound(dfn[x]),l;
    135                     
    136                     if(u == s.end()) u = s.begin();
    137                     //u是后一个
    138                     //l是前一个 
    139                     int t = *u;//防止u改变 
    140                     l = Left(u);
    141                 
    142                     ans -= (dis[rev[t]] + dis[rev[*l]] - 2 * dis[LCA(rev[*l],rev[t])]); 
    143                     ans += (dis[rev[*l]] + dis[x] - 2 * dis[LCA(x,rev[*l])]); 
    144                     ans += (dis[rev[t]] + dis[x] - 2 * dis[LCA(x,rev[t])]); 
    145                 
    146                 }
    147                 s.insert(dfn[x]); 
    148                 break;
    149             }
    150             
    151             case '-':{
    152                     read(x);
    153                     if(s.size()){
    154                         set<int> :: iterator u = s.find(dfn[x]),l,r;
    155     
    156                         l = Left(u);
    157                         
    158                         r = Right(u);
    159                 
    160                     
    161                         ans -= (dis[rev[*l]] + dis[x] - 2 * dis[LCA(x,rev[*l])]); 
    162                         ans -= (dis[rev[*r]] + dis[x] - 2 * dis[LCA(x,rev[*r])]); 
    163                         ans += (dis[rev[*r]] + dis[rev[*l]] - 2 * dis[LCA(rev[*l],rev[*r])]);     
    164 
    165                     }
    166                     s.erase(dfn[x]);
    167                 break;
    168             }
    169             
    170             default:{
    171                 
    172                 put(ans / 2);
    173                 puts("");
    174                 break;
    175                 
    176             }
    177         }
    178     }
    179 }
    180 
    181 int main(){
    182 //    file();
    183     readdata();
    184     work();
    185     return 0;
    186 }
    View Code
    非做顽石不可,哪管他敬仰暗唾
  • 相关阅读:
    #Responsive# 响应式图片//www.w3cplus.com/blog/tags/509.html 整个系列完结。
    用js实现帧动画
    js判断对象是否存在
    canvas
    函数的四种调用模式
    递归真的好难啊!!! 看完之后好多了
    词法作用域
    变量名提升
    ajax调用后台Java
    左图又文字自适应
  • 原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11385528.html
Copyright © 2011-2022 走看看