其他分享
首页 > 其他分享> > loj 10132 异象石

loj 10132 异象石

作者:互联网

题目

传送门:loj10132

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

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

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

输入格式

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

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

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

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

输出格式

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

样例

样例输入

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

 

标签:set,异象石,10132,loj,top,rev,int,maxn,dis
来源: https://www.cnblogs.com/Mandy-H-Y/p/11385528.html