题目链接

  其实这题用Set就完事了但我不会Set

  智商-=inf

  求虚树上所有边权和的两倍。

  具体方式就是splay把所有在虚树上的点存一下,(按照DFS序排序的)每次插入/删除会更新前驱和它、后继和它、前驱和后继的值

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<cstdlib>
#include<map>
#define maxn 200020
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Splay{
struct Node{
int e[],fa;long long val,size;
}tree[maxn];
int root,tot;
Splay(){ root=tot=; }
inline int iden(int x){ return x==tree[tree[x].fa].e[]; }
inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; }
inline void update(int x){ tree[x].size=tree[tree[x].e[]].size+tree[tree[x].e[]].size+; }
void rotate(int x){
int y=tree[x].fa; int r=tree[y].fa;
int sony=iden(x); int sonr=iden(y);
if(root==y) root=x;
int b=tree[x].e[sony^];
connect(b,y,sony);
connect(y,x,sony^);
connect(x,r,sonr);
update(y); update(x);
}
void splay(int pos,int to){
to=tree[to].fa;
while(tree[pos].fa!=to){
if(tree[tree[pos].fa].fa==to) rotate(pos);
else
if(iden(tree[pos].fa)==iden(pos)){ rotate(tree[pos].fa),rotate(pos); }
else {rotate(pos),rotate(pos); }
}
}
inline int create(int fa,int val){
tree[++tot]=(Node){{,},fa,val,};
return tot;
}
inline int build(int val){
if(root==){
root=create(,val);
return root;
}
int now=root;
while(now){
tree[now].size++;
int nxt=val<tree[now].val?:;
if(tree[now].e[nxt]==){
connect(create(now,val),now,nxt);
return tot;
}
now=tree[now].e[nxt];
}
}
inline void insert(int val){
int p=build(val);
splay(p,root);
}
inline int find(int val){
int now=root;
while(now){
if(tree[now].val==val) return now;
int nxt=val<tree[now].val?:;
now=tree[now].e[nxt];
}
return ;
}
void dele(int x){
tree[x].e[]=tree[x].e[]=;
if(x==tot) tot--;
}
void pop(int val){
int now=find(val);
if(now==) return;
splay(now,root);
if(tree[now].e[]==){
root=tree[now].e[];
tree[root].fa=;
dele(now);
return;
}
int deal=tree[now].e[];
while(tree[deal].e[]) deal=tree[deal].e[];
splay(deal,tree[now].e[]);
connect(tree[now].e[],deal,);
root=deal; tree[deal].fa=;
update(deal);
dele(now);
return;
}
inline int lower(int val){
int now=root,ans=-0x7fffffff;
while(now){
if(tree[now].val<val&&tree[now].val>ans) ans=tree[now].val;
int nxt=val<tree[now].val?:;
now=tree[now].e[nxt];
}
return ans;
}
inline int upper(int val){
int now=root,ans=0x7fffffff;
while(now){
if(tree[now].val>val&&tree[now].val<ans) ans=tree[now].val;
int nxt=val<tree[now].val?:;
now=tree[now].e[nxt];
}
return ans;
}
}s; int d[maxn][];
long long w[maxn][];
int dfn[maxn],ID;
int deep[maxn];
bool ext[maxn];
int back[maxn];
long long dis[maxn]; struct Edge{
int next,to;
long long val;
}edge[maxn*];
int head[maxn],num;
inline void add(int from,int to,long long val){
edge[++num]=(Edge){head[from],to,val};
head[from]=num;
} void find(int x,int fa){
dfn[x]=++ID; back[ID]=x;
deep[x]=deep[fa]+;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(to==fa) continue;
dis[to]=dis[x]+edge[i].val;
d[to][]=x; w[to][]=edge[i].val;
find(to,x);
}
return;
} long long calcdis(int x,int y,int opt){
long long ans=;
if(deep[x]<deep[y]) swap(x,y);
int f=deep[x]-deep[y];
for(int i=;(<<i)<=f;++i)
if(f&(<<i)){
ans+=w[x][i];
x=d[x][i];
}
if(x==y) return opt==?ans:x;
for(int i=;i>=;--i){
if(d[x][i]==d[y][i]) continue;
ans+=w[x][i]+w[y][i];
x=d[x][i]; y=d[y][i];
}
return opt==?ans+w[x][]+w[y][]:d[x][];
} int main(){
int n=read(),m=read();
for(int i=;i<n;++i){
int from=read(),to=read(),val=read();
add(from,to,val);
add(to,from,val);
}
find(,);
for(int j=;j<=;++j)
for(int i=;i<=n;++i){
d[i][j]=d[d[i][j-]][j-];
w[i][j]=w[i][j-]+w[d[i][j-]][j-];
}
long long ans=;
while(m--){
int e=read();
int dfe=dfn[e];
if(ext[e]==){
ext[e]=;
int low=s.lower(dfe),upp=s.upper(dfe);
if(low>) ans+=calcdis(back[low],e,);
if(upp<=n) ans+=calcdis(back[upp],e,);
if(low>&&upp<=n) ans-=calcdis(back[low],back[upp],);
s.insert(dfe);
}
else{
ext[e]=;
s.pop(dfe);
int low=s.lower(dfe),upp=s.upper(dfe);
if(low>) ans-=calcdis(back[low],e,);
if(upp<=n) ans-=calcdis(back[upp],e,);
if(low>&&upp<=n) ans+=calcdis(back[low],back[upp],);
}
int last=s.lower(n+),first=s.upper();
long long ret=;
if(last>&&first<=n){ int lca=calcdis(back[last],back[first],);
ret=dis[back[last]]+dis[back[first]]-*dis[lca];
}
printf("%lld\n",ans+ret);
}
return ;
}

【Luogu】P3320寻宝游戏(Splay)的更多相关文章

  1. Luogu P3320 [SDOI2015]寻宝游戏 / 异象石 【LCA/set】

    期末考试结束祭! 在期末考试前最后一发的测试中,异象石作为第二道题目出现QAQ.虽然知道是LCA图论,但还是敲不出来QAQ. 花了两天竞赛课的时间搞懂(逃 异象石(stone.pas/c/cpp)题目 ...

  2. P3320 [SDOI2015]寻宝游戏 解题报告

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

  3. P3320 [SDOI2015]寻宝游戏

    题目 P3320 [SDOI2015]寻宝游戏 做法 很巧妙的一种思路,懂了之后觉得大水题 首先要知道:在一棵树上标记一些点,然后从任意一点出发,遍历所有的的最小路径为\(dfs\)序从小到大遍历 那 ...

  4. [洛谷P3320] SDOI2015 寻宝游戏

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

  5. [bzoj3991] [洛谷P3320] [SDOI2015] 寻宝游戏

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

  6. [BZOJ 3991][SDOI2015]寻宝游戏(dfs序)

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

  7. BZOJ3991 寻宝游戏 LCA 虚树 SET

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

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

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

  9. 【BZOJ】【3991】【SDOI2015】寻宝游戏

    dfs序 我哭啊……这题在考试的时候(我不是山东的,CH大法吼)没想出来……只写了50分的暴力QAQ 而且苦逼的写的比正解还长……我骗点分容易吗QAQ 骗分做法: 1.$n,m\leq 1000$: ...

随机推荐

  1. go语言,安装包fetch error 问题解决方案

    最近需要安装grequests,出现了下面的error [fdf@zxmrlc ~]$ go get github.com/levigross/grequests package golang.org ...

  2. Java代码工具箱之解析单行单列简单Excel

    1. 使用开源工具 jxl.jar 2. 功能:解析常规Excel.xls格式测试可行,xlsx未测试.Excel测试格式为常规类似table这种简单布局文件.第一行为标题,后面行为内容.代码 可正确 ...

  3. oracle常用运维sql语句

    1.查询dblink语句 col owner for a20col db_link for a30col username for a20col host for a30set linesize 12 ...

  4. Mysql占用内存过高的优化过程

    一.环境说明: 操作系统:CentOS 6.5 x86_64 数据库:Mysql 5.6.22 服务器:阿里云VPS,32G Mem,0 swap 二.问题情况: 1.某日发现公司线上系统的Mysql ...

  5. session在C#一般处理程序的调用方式

    在C#中有一个一般处理程序,可以快速地进行一些逻辑运算等功能,但在这个页面上,不能直接选择使用session进行页面间的值的传递,如何使得页面可以使用session呢 在页面开头写上 using Sy ...

  6. keepalived原理(主从配置+haproxy)及配置文件详解

    下图描述了使用keepalived+Haproxy主从配置来达到能够针对前段流量进行负载均衡到多台后端web1.web2.web3.img1.img2.但是由于haproxy会存在单点故障问题,因此使 ...

  7. 一次完整的HTTP请求需要的7个步骤

    HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤: 1:建立TCP连接 在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连 ...

  8. PHP消息队列学习

    在我们平常网站设计时,会遇到“给用户群发短信”,“商城订单系统大批量订单处理”,“商城秒杀活动”等需求,这些功能,都有一个共同的特点:就是在面对高迸发的同时,必须要保证系统处理数据的有效性.那么如何处 ...

  9. python---列表(list)基本操作

    列表基本操作:增.删.查.改等其他操作 创建列表: list1 = ["a","b","c","d"] name_lis ...

  10. day14之模块

    一.列表生成式与生成表达式 1.列表生成式(数据量小) 要求:在列表内造100个元素 示例: l=[] for i in range(100): l.append('egg%s'%i) print(l ...