蓝皮书:异象石 【dfs序+lca】
题目详见蓝皮书【算法竞赛:进阶指南】。
题目大意:
就是给你一颗树,然后我们要在上面进行三种操作:
1.标记某个点 或者 2.撤销某个点的标记 以及 3.询问标记点在树上连通所需的最短总边权
数据范围:
点数以及操作数:1e5,边权:1e9(意思就是答案要 long long 存)。
分析:
这道题比赛的时候看的是真懵逼。。。
表示只会 n^3 做法(最多会n^2),以及特殊形态(比如链或者菊花图)的骗分法。
然鹅正解大概是 $O(n log n)$ 的做法,和树搭上了关系,加上这数据范围...
于是正解真是这个复杂度。(看到标程的时候表示惊讶,我太弱了)
标算就是用的dfs序加上lca的算法(如题)
首先我们不考虑 2、3 操作,我们先考虑如果树上有 k 个点被标记了,我们要得到树上 k 个点连通图的最小总边权。
我们可以在纸上画出这棵树以及标记的点,然后我们从左到右把点连成一块。
这时我们发现每两个相邻的点之间(相当于dfs序)的距离加上最后一个点和第一个点的距离,和正好是答案的两倍。
也就是说,如果把这些标记点按照dfs序排成一列,首尾相连形成一个环的话,答案就是这个环相邻点距离之和除以二。
(这种东西考场上怎么做得出来嘛)
那么我们回到原题,如果用上面的方法暴力处理答案,那么复杂度是 $O(n^{2} log n)$ 的(还不如 我自己想到的 n^2 咧)。
那么我们结合加点删点特殊的性质,以此优化算法复杂度。
我们发现加点其实就是在原环两相邻点之间插入了一个新点,然后原来两个相邻点的贡献没了,但是多了新点与这两个点分别的贡献。
那么删点类似的,就是令原环中某个点与相邻的两个点之间的贡献删除,并且多了这两个点之间的距离的贡献。
于是我们就可以用一个set来维护标记点,然后每次求距离的时候要用到 lca。
(lca建议常数小的树剖,倍增效率感人,tarjan 的话比较冷门基本不考虑)
那么我们就可以愉快地抄敲代码了!
代码 :
//by Judge
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define It set<int>::iterator
#define ll long long
using namespace std;
const int M=1e5+;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1,*p2;
inline int read(){ int x=;
char c=getchar(); while(!isdigit(c)) c=getchar();
for(;isdigit(c);c=getchar()) x=x*+c-''; return x;
} inline int cread(){ char c=getchar();
while(c!='+'&&c!='-'&&c!='?') c=getchar();
return c=='?'?:(c=='+'?:);
} char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(ll x,char chr='\n'){
if(C><<)Ot(); while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]=chr;
} int n,m,pat,tim,head[M],f[M],son[M]; ll ans,dis[M];
int siz[M],top[M],dep[M],dfn[M],p[M]; set<int> s;
struct Edge{ int to,val,nxt;
Edge(int v,int c,int x):to(v),val(c),nxt(x){} Edge(){}
}e[M<<];
inline void add(int u,int v,int c){
e[++pat]=Edge(v,c,head[u]),head[u]=pat;
e[++pat]=Edge(u,c,head[v]),head[v]=pat;
}
#define v e[i].to
void dfs(int u,int fa){
siz[u]=,f[u]=fa,dep[u]=dep[fa]+;
for(int i=head[u];i;i=e[i].nxt) if(v^fa){
dis[v]=dis[u]+e[i].val,
dfs(v,u),siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
} void dfs(int u){
dfn[u]=++tim,p[tim]=u;
if(!top[u]) top[u]=u; if(!son[u]) return ;
top[son[u]]=top[u],dfs(son[u]);
for(int i=head[u];i;i=e[i].nxt)
if(v^f[u]&&v^son[u]) dfs(v);
}
#undef v
inline int lca(int u,int v){
while(top[u]^top[v])
(dep[top[u]]>dep[top[v]])?
u=f[top[u]]:v=f[top[v]];
return dep[u]<dep[v]?u:v;
} inline ll get(int u,int v){
return dis[u]+dis[v]-dis[lca(u,v)]*;
} inline It L(It it){
return (it==s.begin())?--s.end():--it;
} inline It R(It it){
return (it==--s.end())?s.begin():++it;
}
int main(){
n=read();
for(int i=,u,v,c;i<n;++i)
u=read(),v=read(),
c=read(),add(u,v,c);
dfs(,),dfs(),m=read();
for(int opt,x,t;m;--m){
opt=cread(); It it;
if(opt==) print(ans/);
else if(opt==){ x=read();
if(s.size()){
it=s.lower_bound(dfn[x]);
if(it==s.end()) it=s.begin(); t=*L(it);
ans+=get(x,p[t])+get(x,p[*it])-get(p[t],p[*it]);
} s.insert(dfn[x]);
} else if(opt==){ x=read();
if(s.size()>){
it=s.find(dfn[x]),t=*L(it),it=R(it);
ans-=get(x,p[t])+get(x,p[*it])-get(p[t],p[*it]);
} s.erase(dfn[x]);
}
} return Ot(),;
}
蓝皮书:异象石 【dfs序+lca】的更多相关文章
- bzoj2819 DFS序 + LCA + 线段树
https://www.lydsy.com/JudgeOnline/problem.php?id=2819 题意:树上单点修改及区间异或和查询. 思维难度不高,但是题比较硬核. 整体思路是维护每一个结 ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- HDU 3966 dfs序+LCA+树状数组
题目意思很明白: 给你一棵有n个节点的树,对树有下列操作: I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k ...
- HDU 6203 ping ping ping(dfs序+LCA+树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连 ...
- HDU 5296 Annoying problem dfs序 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5296 Description Coco has a tree, w ...
- Gym 101142G : Gangsters in Central City(DFS序+LCA+set)
题意:现在有一棵树,1号节点是水源,叶子节点是村庄,现在有些怪兽会占领一些村庄(即只占领叶子节点),现在要割去一些边,使得怪兽到不了水源.给出怪兽占领和离开的情况,现在要割每次回答最小的割,使得怪兽不 ...
- POJ 2763 Housewife Wind(DFS序+LCA+树状数组)
Housewife Wind Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 11419 Accepted: 3140 D ...
- BZOJ3991 [SDOI2015]寻宝游戏 【dfs序 + lca + STL】
题目 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- BZOJ 4999: This Problem Is Too Simple! DFS序+LCA+树状数组+离线
Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) , ...
随机推荐
- python mysql索引 优化神器explain 慢查询
##############总结########## 数据库中专门帮助用户快速找到数据的一种数据结构 类似于字典的目录的索引 索引的作用:约束和加速查找 工作原理: b+树形结构 最上层是树根,中间是 ...
- java 写一个 map reduce 矩阵相乘的案例
1.写一个工具类用来生成 map reduce 实验 所需 input 文件 下面两个是原始文件 matrix1.txt 1 2 -2 0 3 3 4 -3 -2 0 2 3 5 3 -1 2 -4 ...
- SSM框架的搭建和测试(Spring+Spring MVC+MyBatis)
Spring MVC:MVC框架,通过Model-View-Controller模式很好的将数据,业务与展现进行分离. MyBatis:数据持久层框架 我这里使用的是MyEclipse 2016 CI ...
- HanLP 关键词提取算法分析
HanLP 关键词提取算法分析 参考论文:<TextRank: Bringing Order into Texts> TextRank算法提取关键词的Java实现 TextRank算法自动 ...
- Web获取客户端物理MAC地址(ocx插件)ActiveX控件
主要是通过ActiveX控件 从本地获取到MAC地址,传入到浏览器打开的网页中,再提交到服务器. 具体详解与步骤看文档中: 文件实例包下载 DotNetFX 文件夹附件文件:(可能安装时需用) dot ...
- c# 适配器批量修改
DataTable dt; //在方法外部申明数据表SqlDataAdapter adapter; //在方法外部申明数据适配器 查询方法adapter = new SqlDataAdapter(Sq ...
- rabbitMQ学习3-RPC远程过程调用
将一个函数运行在远程计算机上并且等待获取那里的结果,这个称作远程过程调用(Remote Procedure Call)或者 RPC. RPC是一个计算机通信协议. 比喻 将计算机服务运行理解为厨师做饭 ...
- jupyter notebook出现cannot import name 'create_prompt_application'问题(Died Kernel)
应该是在安装其它python第三方库时更新了prompt-toolkit版本,降级到下面的版本即可: sudo pip install 'prompt-toolkit==1.0.15'
- TensorFlow从入门到理解(二):你的第一个神经网络
运行代码: from __future__ import print_function import tensorflow as tf import numpy as np import matplo ...
- 第26月第13天 hibernate导包
1. https://yq.aliyun.com/ziliao/386827