树剖+线段树||树链剖分||BZOJ2238||Mst
题面:https://www.lydsy.com/JudgeOnline/problem.php?id=2238
思路:先求个最小生成树,然后就对最小生成树上的边做树剖,依次对非树边进行处理,维护非树边两端连成的路径的最小值(用非树边的权值维护),然后对于每个询问,求出覆盖在那条线段上的最小值,用real_sum(最小生成树的边权和)去加加减减就行了。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int maxn=,maxm=,maxw=,inf=<<;
int N,M,x,y,w,Q,edge_head[maxn],num_edge=,edge_head2[maxn],num_edge2=,fa[maxn],real_sum=;
int size[maxn],son[maxn],seg[maxn],rev[maxn],f[maxn],dep[maxn],top[maxn],X,Y,_ans,T;
bool via[maxm],ans=;
inline int rd(){
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return f*x;
}
struct Edge{
int to,dis,nx,from;
}edge[maxm<<];
struct Edge2{
int to,dis,nx,from,id;
}edge2[maxm];
inline void Add_edge(int from,int to,int dis){
edge[++num_edge].nx=edge_head[from];
edge[num_edge].from=from;
edge[num_edge].to=to;
edge[num_edge].dis=dis;
edge_head[from]=num_edge;
return;
}
inline void Add_edge2(int from,int to,int dis){
edge2[++num_edge2].nx=edge_head2[from];
edge2[num_edge2].from=from;
edge2[num_edge2].to=to;
edge2[num_edge2].dis=dis;
edge2[num_edge2].id=num_edge2;
edge_head2[from]=num_edge2;
return;
}
inline bool cmp(const Edge2&a,const Edge2&b){
if(a.dis<b.dis)return ;
return ;
}
inline int getf(int x){
if(fa[x]==x)return x;
fa[x]=getf(fa[x]);
return fa[x];
}
void Kruskal(){
sort(edge2+,edge2+num_edge2+,cmp);
for(int i=;i<=N;i++)fa[i]=i;
int num=;
for(int i=;i<=num_edge2;i++){
int x=edge2[i].from,y=edge2[i].to;
int fx=getf(x),fy=getf(y);
if(fx!=fy){
num++;
fa[fx]=fy;
via[edge2[i].id]=;
real_sum+=edge2[i].dis;
if(num==N-)break;
}
}
if(num!=N-)ans=;
return;
}
inline void Dfs1(int x,int _f){
f[x]=_f;
size[x]=;
dep[x]=dep[_f]+;
for(int i=edge_head[x];i;i=edge[i].nx){
int y=edge[i].to;
if(y!=_f&&((((i&)==)&&via[(i>>)+])||(((i&)==)&&via[i>>]))){
Dfs1(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]])son[x]=y;
}
}
return;
}
inline void Dfs2(int x){
if(son[x]){
int y=son[x];
top[y]=top[x];
seg[y]=++seg[];
rev[seg[]]=y;
Dfs2(y);
}
for(int i=edge_head[x];i;i=edge[i].nx){
int y=edge[i].to;
if(top[y]==&&((((i&)==)&&via[(i>>)+])||(((i&)==)&&via[i>>]))){
top[y]=y;
seg[y]=++seg[];
rev[seg[]]=y;
Dfs2(y);
}
}
return;
}
struct Tree{
int l,r,mina,lazy;
}t[maxn<<];
inline void Build(int x,int l,int r){
t[x].l=l;t[x].r=r;t[x].mina=inf;t[x].lazy=inf;
if(l==r)return;
int ls=x<<,rs=x<<|,mid=(l+r)>>;
Build(ls,l,mid);Build(rs,mid+,r);
return;
}
inline void Pushdown(int x){
int ls=x<<,rs=x<<|,lazy=t[x].lazy;
if(lazy!=inf){
t[ls].mina=min(t[ls].mina,lazy);t[rs].mina=min(t[rs].mina,lazy);
t[ls].lazy=min(t[ls].lazy,lazy);t[rs].lazy=min(t[rs].lazy,lazy);
t[x].lazy=inf;
}
return;
}
inline void Update(int x,int ql,int qr,int e){
int l=t[x].l,r=t[x].r;
if(ql<=l&&r<=qr){
t[x].mina=min(t[x].mina,e);
t[x].lazy=min(t[x].lazy,e);
return;
}
int ls=x<<,rs=x<<|,mid=(l+r)>>;
Pushdown(x);
if(ql<=mid)Update(ls,ql,qr,e);
if(qr>mid)Update(rs,ql,qr,e);
return;
}
inline void Query(int x,int q){
int l=t[x].l,r=t[x].r;
if(q==l&&l==r){
_ans=min(_ans,t[x].mina);
return;
}
int mid=(l+r)>>,ls=x<<,rs=x<<|;
Pushdown(x);
if(q<=mid)Query(ls,q);
else Query(rs,q);
return;
}
inline void Work(int x,int y,int dis){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
Update(,seg[fx],seg[x],dis);
x=f[fx];fx=top[x];
}
if(dep[x]>dep[y])swap(x,y);
if(x==y)return;
Update(,seg[x]+,seg[y],dis);
return;
}
int main(){
N=rd();M=rd();
for(int i=;i<=M;i++){
x=rd();y=rd();w=rd();
Add_edge2(x,y,w);
Add_edge(x,y,w);
Add_edge(y,x,w);
}
Kruskal();
scanf("%d",&Q);
Dfs1(,);
seg[]=seg[]=rev[]=top[]=;
Dfs2();
Build(,,seg[]);
for(int i=;i<=M;i++)if(via[i]==)Work(edge[i<<].from,edge[i<<].to,edge[i<<].dis);
while(Q--){
scanf("%d",&T);
if(ans==){
puts("Not connected");
continue;
}
if(via[T]==)printf("%d\n",real_sum);
else{
X=edge[T<<].from,Y=edge[T<<].to;_ans=inf;
if(dep[X]>dep[Y])Query(,seg[X]);else Query(,seg[Y]);
if(_ans==inf){
puts("Not connected");
continue;
}
_ans=real_sum-edge[T<<].dis+_ans;
printf("%d\n",_ans);
}
}
return ;
}
后记:“&”的优先级小于“==”的优先级;线段树查询时要注意ql不能大于qr;边权下移后处理点权时要小心;什么情况要pushdown、pushup要考虑清楚;我的线段树真菜
树剖+线段树||树链剖分||BZOJ2238||Mst的更多相关文章
- 【BZOJ5210】最大连通子块和 树剖线段树+动态DP
[BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...
- BZOJ_2238_Mst_树剖+线段树
BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...
- BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树
BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...
- BZOJ_2157_旅游_树剖+线段树
BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...
- [LNOI2014]LCA(树剖+线段树)
\(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...
- [CF1007D]Ants[2-SAT+树剖+线段树优化建图]
题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...
- LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)
题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...
- BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)
传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...
随机推荐
- V-rep学习笔记:关节力矩控制
Torque or force mode When the joint motor is enabled and the control loop is disabled, then the join ...
- libmongoc关于\$pullAll和\$addToSet的一个使用问题记录
问题描述及测试结果 在使用mongodb时,对一个document中的数组成员进行更新的时候,可以使用$pull $push $pop $addToSet $pullAll和$each $positi ...
- 002_ASP.NET 换主题
网盘下载地址 http://pan.baidu.com/s/1c1VzIla 在线观看地址 http://www.bamn.cn/course/lesson/2 课程介绍 ASP.NET 实现更换主题 ...
- dos 批量重命名 bat
@echo off setlocal enabledelayedexpansion echo %var% set /a i = i + var for %%x in (*) do ( if not & ...
- Spring Boot优化
针对目前的容器优化,目前来说没有太多地方,需要考虑如下几个点: 线程数 超时时间 jvm优化 首先线程数是一个重点,初始线程数和最大线程数,初始线程数保障启动的时候,如果有大量用户访问,能够很稳定的接 ...
- 在 word 中对正文和目录进行分节显示页码
使用版本 word 2016 使目录独占一页:在正文第一页的第一个字符前插入分节符下一页(布局--分节符--下一页),此时会在正文第一个字符前插入分节符.在之前插入一张空白页,用于插入目录.(插入 - ...
- Android解决NDK not configured问题
问题描述: // Error:Execution failed for task ':SoftkeyApp:compileDebugNdk'. // > NDK not configured. ...
- java 路径分隔符自动适配
linux文件路径分隔符为 / ,windows的文件路径分隔符为 \ ,在开发项目过程中不确定用户使用何种操作系统,就需要自动适配路径. 目前已知java提供两种方法获取文件路径分割符: F ...
- 用pigz代替gzip -- 并行压缩软件
用pigz代替gzip By yejr on 03 十二月 2012 pig是个啥东东?官网:http://zlib.net/pigz一句话简介: A parallel implementation ...
- linux 重启和关机
重启命令有:reboot, shutdown -ry 0关机命令有:poweroff, shutdown -hy 0