bzoj 2238 Mst —— 树剖+mn标记永久化
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238
看了半天...
首先,想要知道每条边删除之后的替代中最小的那个;
反过来看,每条不在 MST 上的边如果加入,会对一条路径产成影响,具体来说,就是这条路径上的所有边在被删除后,可以考虑用这条非 MST 边替代;
于是就可以用树剖,对每条非 MST 边,维护一下路径上的最小值;
于是写了一下,但WA了,仔细看看,mn 和 lzy 更新的地方似乎有点不太对,比如没有更新 mn 也可以更新 lzy 什么的...(因为 mn 还被左右儿子更新,所以可能比 lzy 更小...)
反正是取min,标记永久化很方便呢(干脆没有 lzy ),于是又跟 Narh 学了一下 mn 标记永久化的写法。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
int const xn=,xm=1e5+,inf=0x3f3f3f3f;
int n,m,hd[xn],ct,nxt[xn<<],to[xn<<],dep[xn],siz[xn],son[xn],dfn[xn],top[xn],fa[xn],tim;
int mn[xn<<],lzy[xn<<],ans;
bool use[xm],fl;
struct N{int u,v,w,id;}e[xm];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
bool cmp(N x,N y){return x.w<y.w;}
bool cmp2(N x,N y){return x.id<y.id;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void dfs(int x)
{
dep[x]=dep[fa[x]]+; siz[x]=;
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==fa[x])continue;
fa[u]=x; dfs(u); siz[x]+=siz[u];
if(siz[u]>siz[son[x]])son[x]=u;
}
}
void dfs2(int x)
{
dfn[x]=++tim;
if(son[x])top[son[x]]=top[x],dfs2(son[x]);
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==fa[x]||u==son[x])continue;
top[u]=u; dfs2(u);
}
}
void pushdown(int x)
{
if(lzy[x]==-)return;
if(lzy[x]<mn[ls])mn[ls]=lzy[x],lzy[ls]=lzy[x];
if(lzy[x]<mn[rs])mn[rs]=lzy[x],lzy[rs]=lzy[x];
lzy[x]=-;
}
void update(int x,int l,int r,int L,int R,int d)
{
// if(l>=L&&r<=R){if(d<mn[x])mn[x]=d,lzy[x]=d; return;}
// pushdown(x);
if(l>=L&&r<=R){mn[x]=min(mn[x],d); return;}
// mn[x]=min(mn[x],d);
if(mid>=L)update(ls,l,mid,L,R,d);
if(mid<R)update(rs,mid+,r,L,R,d);
// mn[x]=min(mn[ls],mn[rs]);
}
void change(int x,int y,int d)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(,,n,dfn[top[x]],dfn[x],d);
x=fa[top[x]];
}
if(x==y)return;
if(dep[x]<dep[y])swap(x,y);
update(,,n,dfn[y]+,dfn[x],d);
}
int query(int x,int l,int r,int pos)
{
if(l==r)return mn[x];
// pushdown(x);
// if(pos<=mid)return query(ls,l,mid,pos);
// else return query(rs,mid+1,r,pos);
if(pos<=mid)return min(mn[x],query(ls,l,mid,pos));
else return min(mn[x],query(rs,mid+,r,pos));
}
int main()
{
n=rd(); m=rd();
for(int i=,x,y,z;i<=m;i++)e[i].u=rd(),e[i].v=rd(),e[i].w=rd(),e[i].id=i;
sort(e+,e+m+,cmp);
for(int i=;i<=n;i++)fa[i]=i; int cnt=;
for(int i=;i<=m;i++)
{
int x=find(e[i].u),y=find(e[i].v);
if(x==y)continue;
add(e[i].u,e[i].v); add(e[i].v,e[i].u); ans+=e[i].w;
fa[x]=y; cnt++; use[e[i].id]=;//id
if(cnt==n-)break;
}
if(cnt<n-)fl=;
if(!fl)//省时
{
fa[]=; dfs(); top[]=; dfs2();
memset(mn,0x3f,sizeof mn); memset(lzy,-,sizeof lzy);
sort(e+,e+m+,cmp2);
for(int i=;i<=m;i++)
{
if(use[i])continue;
change(e[i].u,e[i].v,e[i].w);
}
}
int q=rd();
for(int i=,x;i<=q;i++)
{
x=rd();
if(fl){puts("Not connected"); continue;}
if(!use[x]){printf("%d\n",ans); continue;}
int k=query(,,n,max(dfn[e[x].u],dfn[e[x].v]));
if(k==inf)puts("Not connected");
else printf("%d\n",ans-e[x].w+k);
}
return ;
}
bzoj 2238 Mst —— 树剖+mn标记永久化的更多相关文章
- bzoj 2238 Mst——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 一条非树边可以对一条链的树边产生影响.注意是边,所以把边下放到点上,只要跳 top 时 ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- bzoj 2238 Mst
显然先求出最小生成树 如果删的是非树边就不用管,还是能取最小生成树 如果删的是树边就有非树边可以替代它 反向考虑,每条非树边可以替代最小生成树上一条路径的边 所以树剖加线段树,对每条非树边在树上更新对 ...
- BZOJ 2238: Mst DFS序+KDtree
明明可以用二维数点来做啊,网上为什么都是树剖+线段树呢 ? code: #include <cstdio> #include <cstring> #include <al ...
- BZOJ 1798 (线段树||分块)的标记合并
我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...
- BZOJ 3083: 遥远的国度 (树剖+线段树)
传送门 解题思路 前两个操作都比较基础.对于第三个操作分类讨论一下,首先如果当前根不是要操作点的子树,那么就无影响,直接查询操作点的子树即可.第二种是当前根是操作点的子树,那就找到当前根到操作点这条链 ...
- BZOJ 3110 线段树套线段树
思路: 外围一个权值线段树 里面是个区间线段树 搞一个标记永久化 //By SiriusRen #include <cstdio> #include <cstring> #in ...
- [HNOI2015]开店(树剖+主席树+标记永久化)
听说正解点分树?我不会就对了 此题是 \([LNOI2014]LCA\) 强化版,也是差分一下,转化为区间加区间和 不过权值有大小要求,那么我们按照权值排序,依次加入主席树,询问的时候 \(lower ...
- bzoj 1513 POI2006 Tet-Tetris 3D 二维线段树+标记永久化
1511: [POI2006]OKR-Periods of Words Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 351 Solved: 220[S ...
随机推荐
- 心脏滴血漏洞复现(CVE-2014-0160)
漏洞范围: OpenSSL 1.0.1版本 漏洞成因: Heartbleed漏洞是由于未能在memcpy()调用受害用户输入内容作为长度参数之前正确进 行边界检查.攻击者可以追踪OpenSSL所分配的 ...
- Java中的final关键字(转)
Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...
- scrapy的自动限速(AutoThrottle)扩展
该扩展能根据Scrapy服务器及您爬取的网站的负载自动限制爬取速度. 设计目标 更友好的对待网站,而不使用默认的下载延迟0. 自动调整scrapy来优化下载速度,使得用户不用调节下载延迟及并发请求数来 ...
- 梯度下降和EM算法,kmeans的em推导
I. 牛顿迭代法给定一个复杂的非线性函数f(x),希望求它的最小值,我们一般可以这样做,假定它足够光滑,那么它的最小值也就是它的极小值点,满足f′(x0)=0,然后可以转化为求方程f′(x)=0的根了 ...
- javaproject积累——树形结构的操作
近期一直被树形结构整的非常头大,又是递归.又是循环.可是,好在我们在经历了千辛万苦后.最终弄出来了.事实上就是组织机构的常规操作,有些是我们过度设计.有些是我们想错了.而对数的逻辑读取,我们就属于想错 ...
- 【转载】WebService相关概念
一.序言 大家或多或少都听过 WebService(Web服务),有一段时间很多计算机期刊.书籍和网站都大肆的提及和宣传WebService技术,其中不乏很多吹嘘和做广告的成 分.但是不得不承认的是W ...
- Robot Framework自己主动化測试框架之我见
一些自己主动化測试现状: 盲目的去做自己主动化,终于以失败告终. 觉得是能提高效率的事情.却推广不下去: 事实上上述问题产生的原因是: 自己主动化測试案例稳定性不高,可维护性比較差: 自己主动化測试工 ...
- T-SQL查询进阶--变量
概述 变量对于一种语言是必不可少的一部分,当然,对于T-SQL来讲也是一样.在简单查询中,往往很少用到变量,但无论对于复杂的查询或存储过程中,变量都是必不可少的一部分. 变量的种类 在T-SQL中,变 ...
- java的gradle项目的基本配置
plugins { id 'org.springframework.boot' version '2.1.4.RELEASE' id 'java' } apply plugin: 'io.spring ...
- Spring中的IOC容器(学习笔记)
如何将Bean配置到Spring的Bean容器中 通过xml配置文件: Bean实现类来自第三方类库:如“DataSource”等 需要命名空间配置如:context,aop,mvc等 ...