树剖+线段树||树链剖分||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$ 的简单路径上的点可 ...
随机推荐
- flex bison
https://www.gnu.org/software/bison/manual/bison.html https://blog.csdn.net/sirouni2003/article/detai ...
- Sequel Pro for Mac(MySQL 数据库管理工具)破解版安装
1.软件简介 Sequel Pro 是一款管理 Mysql 的工具,界面简洁易用. 2.功能特色 FULL MYSQL SUPPORT Sequel Pro is a fast, easy-to ...
- JS放在博客里面运行
<ol><li>测试的内容</li><li>测试的内容</li><li>测试的内容</li><li>测试 ...
- 【Python】将python3.6软件的py文件打包成exe程序
下载pyinstaller pyinstaller 改变图标 pyinstaller -F --icon=my.ico xxx.py 采用命令行操作的办法 在cmd命令行中,输入代码: 首先,前往Py ...
- 解决 meld 出现 locale.setlocale(locale.LC_ALL,'') 失败的问题
. . . . . meld 是一款免费的文件比较工具,官网地址:http://meldmerge.org/ 在 Linux 环境使用 meld 的时候,可能会由于语言区域的配置问题导致它无法启动,会 ...
- linux下依赖库的版本问题引起的安装失败:libssl-dev版本问题无法安装 :libssl-dev : 依赖: libssl1.0.0 (= 1.0.1-4ubuntu3) 但是 1.0.1-4ubuntu5.31 正要被安装
依赖库版本问题引起的安装失败解决方法如下有两种: 1.是由于源需要更新,如下操作: libssl-dev : 依赖: libssl0.9.8 (= 0.9.8o-1ubuntu4) 但是 0.9.8o ...
- 很好的git教程
http://www.liaoxuefeng.com/这里的git教程很好,我是从这入的门.
- 多线程开发之二 NSOperation
效果如下: ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UITableViewControll ...
- 07装饰模式Decorator
一.什么是装饰模式 装饰( Decorator )模式又叫做包装模式.通 过一种对客户端透明的方式来扩展对象的功能, 是继承关系的一个替换方案. 二.装饰模式的结构 三.装饰模式的角色和职责 抽象组件 ...
- 使用WPF Animated GIF实现GIF图片的播放
这个类库很方便,也很简单:http://wpfanimatedgif.codeplex.com/ 参考博客:http://blog.csdn.net/gqqnb/article/details/721 ...