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 时 ...
随机推荐
- javascript 浏览器定位
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- MySQL Authentication plugin 'caching_sha2_password' cannot be loaded
很多用户在使用Navicat Premium 12连接MySQL数据库时会出现Authentication plugin 'caching_sha2_password' cannot be loade ...
- 前端每日实战:47# 视频演示如何用纯 CSS 创作一个蝴蝶标本展示框
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/xzgZzQ 可交互视频教程 此视频 ...
- jQuery-Ajax请求Json数据并加载在前端页面,附视频教程讲解!
Ajax技术应用广泛,这种异步加载技术,无需刷新网页即可更新网站内容,全局或者局部均可,所以大家应该学会这种技巧,把技术用上来. 创建demo.json文件,用来做数据源: { "t ...
- C# 批量修改考勤设备时间
自己工作中用到的小程序,每次远行后批量改一次 如下: 其中的zkemkeeper是中控的相关组件,因是系统组件,须要先注册相关文件后才有效 using System; using System.Col ...
- 【leetcode】1020. Number of Enclaves
题目如下: Given a 2D array A, each cell is 0 (representing sea) or 1 (representing land) A move consists ...
- 回炉Spring--Bean生命周期及AOP
Spring容器: 在基于Spring的应用中,你的应用对象生存于Spring容器(container)中,Spring容器负责创建对象,装配它们,配置它们并管理它们的整个生命周期,从生存到死亡.(在 ...
- Redis5离线安装
1. 直接上redis官网安装包, 然后上传服务器 https://redis.io/download 2. 解压 tar -zxvf redis-5.0.6.tar.gz 3. 进入redis根目标 ...
- SGU 176 (有源汇最小流)
转载:http://blog.csdn.net/dan__ge/article/details/51207951 题意:n个节点,m条路径,接下来m行a,b,c,d,如果d等于1,则a到b的流量必须为 ...
- 【CF1210C】Kamil and Making a Stream(vector,数论,树)
题意:给定一棵n个点带点权的树,i号点的点定义f(i,j)为i到j路径上所有点的gcd,其中i是j的一个祖先,求所有f(i,j)之和mod1e9+7 2<=n<=1e5,0<=a[i ...