bzoj3991 [Sdoi2015]寻宝游戏 set动态维护虚树+树链求并
题目大意:支持多次操作,增加或删除一个关键点
动态维护虚树边权和*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动态维护虚树+树链求并的更多相关文章
- [BZOJ3991][SDOI2015]寻宝游戏
[BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...
- CH#56C 异象石 和 BZOJ3991 [SDOI2015]寻宝游戏
异象石 CH Round #56 - 国庆节欢乐赛 描述 Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图.这张地图上 ...
- bzoj3991 [SDOI2015]寻宝游戏 树链的并
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3991 题解 貌似这个东西叫做树链的并,以前貌似写过一个类似的用来动态维护虚树. 大概就是最终的 ...
- [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set
寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- bzoj3991: [SDOI2015]寻宝游戏--DFS序+LCA+set动态维护
之前貌似在hdu还是poj上写过这道题. #include<stdio.h> #include<string.h> #include<algorithm> #inc ...
- 【dfs序】【set】bzoj3991 [Sdoi2015]寻宝游戏
在考试代码的基础上稍微改改就a了……当时为什么不稍微多想想…… 插入/删除一个新节点时就把其dfn插入set/从set中删除. 当前的答案就是dfn上相邻的两两节点的距离和,再加上首尾节点的距离. 比 ...
- bzoj 3991: [SDOI2015]寻宝游戏 虚树 set
目录 题目链接 题解 代码 题目链接 bzoj 3991: [SDOI2015]寻宝游戏 题解 发现每次答案就是把虚树上的路径*2 接在同一关键点上的点的dfs序是相邻的 那么用set动态维护dfs序 ...
- 【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set
[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩 ...
随机推荐
- POJ 1821 单调队列+dp
题目大意:有K个工人,有n个墙,现在要给墙涂色.然后每个工人坐在Si上,他能刷的最大范围是Li,且必须是一个连续子区间,而且必须过Si,他刷完后能获得Pi钱 思路:定义dp[i][j]表示前i个人,涂 ...
- AIM Tech Round 3 (Div. 2) B 数学+贪心
http://codeforces.com/contest/709 题目大意:给一个一维的坐标轴,上面有n个点,我们刚开始在位置a,问,从a点开始走,走n-1个点所需要的最小路程. 思路:我们知道,如 ...
- 把一个 int 数字 n 格式化成16进制的字符串(前面补零成0位)
例如,输入n=10,要求输出 0x0000000A; C++: sprintf( buffer, "0x%08X", n); C#: string s = string.F ...
- wireshark 使用技巧
Wireshark使用技巧-GeoIP显示IP地理位置 在使用Wireshark时,有的时候需要知道抓取的报文中某个IP地址的具体地理位置,笨一点的方法是将IP地址复制,然后通过一些软件或 ...
- 处理Easyui的Datagrid无法及时刷新问题
在Easyui中打打开窗口dialog控件,当做完修改操作之后,关闭dialog控件刷新Datagrid,有时候无法及时刷新. 1.JavaScript中的代码 function doEdit(){ ...
- error: QApplication: No such file or directory
尝试用Qt5编译Qt4的工程.你会遇到下面的问题: 错误:C1083: 无法打开包括文件:“QApplication”: No such file or directory 出现原因:Qt5里不再用Q ...
- Android 自定义 SpinnerButton(转)
Android 自定义 SpinnerButton 模仿Android4.0的Spinner Button写的一个MySpinnerButton.这样在1.6~4.0.4版本都可以实现这种下拉框的效果 ...
- java中的装饰设计模式,浅谈与继承之间的区别
最初接触装饰设计模式,一直搞不懂这么做的意义是什么,看了网上很多的资料,对于与继承的区别并没有很清楚的分析,直到看到这篇博客:http://www.cnblogs.com/rookieFly-tdii ...
- Chapter 1 First Sight——6
"You didn't need to do that, Dad. I was going to buy myself a car." 你不需要这样,父亲,我会自己买一辆车的 &q ...
- 套接字和域名系统DNS
套接字产生的原因: 当应用进程通过传输层进行通信时 ,TCP和 UDP将面临同时为多个应用进程提供并行通信的问题.多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据. 为了区别每 ...