BZOJ 2238: Mst DFS序+KDtree
明明可以用二维数点来做啊,网上为什么都是树剖+线段树呢 ?
code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100006
#define inf 1000000
#define ll long long
#define IO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
namespace KD { int d;
struct node {
int ch[2],p[2],mn[2],mx[2],Min,val;
}t[N]; bool cmp(node a,node b)
{
return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];
} int isin(int x1,int y1,int x2,int y2,int x)
{
if(t[x].mn[0]>=x1&&t[x].mx[0]<=y1&&t[x].mn[1]>=x2&&t[x].mx[1]<=y2)
return 1;
return 0;
} int isout(int x1,int y1,int x2,int y2,int x)
{
if(x1>t[x].mx[0]||y1<t[x].mn[0]||x2>t[x].mx[1]||y2<t[x].mn[1])
return 1;
return 0;
} void pushup(int x,int y)
{
for(int i=0;i<2;++i)
{
t[x].mn[i]=min(t[x].mn[i],t[y].mn[i]);
t[x].mx[i]=max(t[x].mx[i],t[y].mx[i]);
}
t[x].Min=min(t[x].Min,t[y].Min);
} int build(int l,int r,int o)
{
d=o;
int mid=(l+r)>>1;
nth_element(t+l,t+mid,t+1+r,cmp);
t[mid].mn[0]=t[mid].mx[0]=t[mid].p[0];
t[mid].mn[1]=t[mid].mx[1]=t[mid].p[1];
t[mid].Min=t[mid].val;
if(mid>l)
{
t[mid].ch[0]=build(l,mid-1,o^1);
pushup(mid,t[mid].ch[0]);
}
if(r>mid)
{
t[mid].ch[1]=build(mid+1,r,o^1);
pushup(mid,t[mid].ch[1]);
}
return mid;
} int query(int x1,int y1,int x2,int y2,int x)
{
if(isout(x1,y1,x2,y2,x)) return inf;
if(isin(x1,y1,x2,y2,x)) return t[x].Min;
int re=inf;
if(t[x].p[0]>=x1&&t[x].p[0]<=y1&&t[x].p[1]>=x2&&t[x].p[1]<=y2)
{
re=min(re,t[x].val);
}
if(t[x].ch[0]) re=min(re,query(x1,y1,x2,y2,t[x].ch[0]));
if(t[x].ch[1]) re=min(re,query(x1,y1,x2,y2,t[x].ch[1]));
return re;
} };
namespace T {
int p[N]; void init(int x)
{
for(int i=1;i<=x;++i) p[i]=i;
} int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
} int merge(int x,int y)
{
x=find(x),y=find(y);
if(x!=y)
{
p[x]=y;
return 1;
}
else return 0;
} }; struct Edge {
int x,y,c,id;
Edge(int x=0,int y=0,int c=0,int id=0):x(x),y(y),c(c),id(id){}
bool operator<(Edge a) const { return c<a.c; }
}e[N];
int n,m,edges,dfn;
int hd[N],to[N<<1],nex[N<<1],val[N<<1],mk[N],fa[N],st[N],ed[N],go[N]; void add(int u,int v,int c)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
} void dfs(int u,int ff)
{
fa[u]=ff;
st[u]=++dfn;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff) continue;
dfs(v,u);
}
ed[u]=dfn;
} int main()
{
// IO("input");
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=m;++i)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
e[i]=Edge(x,y,z,i);
}
sort(e+1,e+1+m);
T::init(n);
ll ans=0;
int cn=0,tot=0;
for(i=1;i<=m;++i)
{
if(T::merge(e[i].x,e[i].y))
{
ans+=(ll)e[i].c;
mk[e[i].id]=1,++cn;
add(e[i].x,e[i].y,e[i].c);
add(e[i].y,e[i].x,e[i].c);
}
}
if(cn==n-1) dfs(1,0);
for(i=1;i<=m;++i)
{
go[e[i].id]=i;
if(!mk[e[i].id])
{
int x=e[i].x;
int y=e[i].y;
if(st[x]>st[y]) swap(x,y);
++tot;
KD::t[tot].val=e[i].c;
KD::t[tot].p[0]=st[x];
KD::t[tot].p[1]=st[y];
}
}
int root=KD::build(1,tot,0);
int q;
scanf("%d",&q);
for(i=1;i<=q;++i)
{
int cur;
scanf("%d",&cur);
if(cn<n-1) printf("Not connected\n");
else
{
if(!mk[cur]) printf("%lld\n",ans);
else
{
cur=go[cur];
int x=e[cur].x;
int y=e[cur].y;
if(fa[y]==x) swap(x,y);
int re=inf;
if(st[x]>1)
{
re=min(re,KD::query(1,st[x]-1,st[x],ed[x],root));
}
if(ed[x]<n)
{
re=min(re,KD::query(st[x],ed[x],ed[x]+1,n,root));
}
if(re==inf) printf("Not connected\n");
else printf("%lld\n",ans-e[cur].c+re);
}
}
}
return 0;
}
BZOJ 2238: Mst DFS序+KDtree的更多相关文章
- 【bzoj4154】(dfs序+kd-tree)
传送门 题意: 给出一颗以\(1\)为根的有根树,初始所有结点的颜色为\(1\). 之后有两个操作,一种是每次将距离\(a\)结点距离不超过\(l\)的所有儿子结点颜色染为\(c\):另一种是询问结点 ...
- [BZOJ 2819]NIM(dfs序维护树上xor值)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2819 分析: 树上的nim游戏,关键就是要判断树上的一条链的异或值是否为0 这个题目有 ...
- BZOJ 4034 BIT & Dfs序
调了恒久突然发现输出优化忘记带负号了.. 就是差分树状数组维护Dfs序即可. #include <iostream> #include <cstring> #include & ...
- BZOJ 3083: 遥远的国度 dfs序,树链剖分,倍增
今天再做一天树的题目,明天要开始专攻图论了.做图论十几天之后再把字符串搞搞,区域赛前再把计几看看. 3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 ...
- BZOJ 2819: Nim dfs序维护树状数组,倍增
1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家.2.把堆v中的石子数变为k. 分析: ...
- BZOJ 1103 大都市(dfs序+树状数组)
应该是一道很水的题吧... 显然可以用树链剖分解决这个问题,虽然不知道多一个log会不会T.但是由于问题的特殊性. 每次修改都是将边权为1的边修改为0,且询问的是点i到根节点的路径长度. 令点i到根节 ...
- bzoj 2238 Mst —— 树剖+mn标记永久化
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 看了半天... 首先,想要知道每条边删除之后的替代中最小的那个: 反过来看,每条不在 ...
- bzoj 2238 Mst
显然先求出最小生成树 如果删的是非树边就不用管,还是能取最小生成树 如果删的是树边就有非树边可以替代它 反向考虑,每条非树边可以替代最小生成树上一条路径的边 所以树剖加线段树,对每条非树边在树上更新对 ...
- bzoj 2238 Mst——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 一条非树边可以对一条链的树边产生影响.注意是边,所以把边下放到点上,只要跳 top 时 ...
随机推荐
- [AtCoder] Yahoo Programming Contest 2019
[AtCoder] Yahoo Programming Contest 2019 很遗憾错过了一场 AtCoder .听说这场是涨分场呢,于是特意来补一下题. A - Anti-Adjacency ...
- 提高wifi速度的设置办法
系列的提高wifi速度的设置办法 在DNS一栏有你们家的地址,在你们家的地址前输入“114.114.114.114”并以“,”结尾(注意:要用英文输入法哦.) 设置完后点击左上角的“无线局域网”回到初 ...
- 企业打开云HBase的正确方式,来自阿里云云数据库团队的解读
一.HBase的历史由来 HBase是一个开源的非关系型分布式数据库(NoSQL),基于谷歌的BigTable建模,是一个高可靠性.高性能.高伸缩的分布式存储系统,使用HBase技术可在廉价PC Se ...
- 4412 linux延时和时间
基本知识 • linux中延时函数很简单,却经常用到• 在操作系统中和单片机处理延时方式就完全不一样了,不可能是使用for循环浪费系统资源.而是有专门的接口函数• linux系统编程中常用的延时函数: ...
- BZOJ 1018: [SHOI2008]堵塞的交通traffic(线段树分治+并查集)
传送门 解题思路 可以离线,然后确定每个边的出现时间,算这个排序即可.然后就可以线段树分治了,连通性用并查集维护,因为要撤销,所以要按秩合并,时间复杂度\(O(nlog^2 n)\) 代码 #incl ...
- LintCode之回文数
题目描述: 我的代码: public class Solution { /* * @param num: a positive number * @return: true if it's a pal ...
- Python 进阶_生成器 & 生成器表达式
目录 目录 相关知识点 生成器 生成器 fab 的执行过程 生成器和迭代器的区别 生成器的优势 加强的生成器特性 生成器表达式 生成器表达式样例 小结 相关知识点 Python 进阶_迭代器 & ...
- delphi xe2 opencv 学习
安装环境 delphi xe2 + opencv opencv 从下面的地方下载 https://github.com/Laex/Delphi-OpenCV然后按照 此网站的 说明 一项以项的 安装 ...
- crontab 使用
1. 安装,结构 yum install cronie 结构: * * * * * [分钟] [小时] [每月的某一天] [每年的某一月] [每周的某一天] 2.命令 1,添加或更新crontab中的 ...
- 小程序BUTTON点击,去掉背景色
添加hover-class <button form-type="submit" hover-class="btn-hover"></but ...