题面: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的更多相关文章

  1. 【BZOJ5210】最大连通子块和 树剖线段树+动态DP

    [BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...

  2. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  3. BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...

  4. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

  5. [LNOI2014]LCA(树剖+线段树)

    \(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...

  6. [CF1007D]Ants[2-SAT+树剖+线段树优化建图]

    题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...

  7. LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)

    题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...

  8. BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)

    传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...

  9. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

随机推荐

  1. Javascript框架的自定义事件(转)

    很多 javascript 框架都提供了自定义事件(custom events),例如 jquery.yui 以及 dojo 都支持“document ready”事件.而部分自定义事件是源自回调(c ...

  2. ftrace 示例

    假设debugfs已经挂载到了/sys/kernel/debug目录下,下面的小脚本用来抓取unlink系统调用的耗时: cd /sys/kernel/debug/tracing echo funct ...

  3. PhoneGap-Android-HTML5-WebSocket

    https://github.com/FreakDev/PhoneGap-Android-HTML5-WebSocket

  4. Socket网络编程--小小网盘程序(1)

    这个系列是准备讲基于Linux Socket进行文件传输.简单的文件传输就是客户端可以上传文件,可以从服务器端下载文件.就这么两个功能如果再加上身份验证,就成了FTP服务器了,如果对用户的操作再加上一 ...

  5. Socket网络编程--网络爬虫(2)

    上一小节,我们实现了下载一个网页.接下来的一步就是使用提取有用的信息.如何提取呢?一个比较好用和常见的方法就是使用正则表达式来提取的.想一想我们要做个什么样的网络爬虫好呢?我记得以前好像博客园里面有人 ...

  6. 菜鸟教程之工具使用(八)——EGit禁止自动转换回车换行符

    众所周知,Windows和Linux系统的回车换行是不一样的.想要进一步了解它们的可以阅读下面的介绍,不感兴趣的可以直接跳过. 产生背景 关于“回车”(carriage return)和“换行”(li ...

  7. 【原】在Matplotlib绘图过程中设置X轴的刻度和显示文本

    使用Matplotlib进行绘图时,当x轴的数据太多的时候,就需要设置x轴的刻度和显示文本,关键代码如下: 绘图结果如下:

  8. .NET实现事务的编码方式

    1,在T-SQL语句中用begin tran,end tran的方式 begin tran --select top(1) * from dbo.test with(updlock) update t ...

  9. JavaScript Scroll家族以及封装

    JavaScript Scroll家族以及封装 scrollTop & scrollLeft 别卷去的值,就是当滑动滚轮浏览网页的时候,网页隐藏在屏幕上方或左侧的距离 获得scrollTop ...

  10. 转载:CSS垂直居中总结

    原文地址:http://www.cnblogs.com/dojo-lzz/p/4419596.html 工作中遇到垂直居中问题,特此总结了一下几种方式与大家分享.本文讨论的垂直居中仅支持IE8+ 1. ...