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 时 ...
随机推荐
- 前端每日实战:76# 视频演示如何用纯 CSS 创作一组单元素办公用品(内含2个视频)
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/oMgmwB 可交互视频 此视频是可 ...
- 02 spring security 自定义用户认证流程
1. 自定义登录页面 (1)首先在static目录下面创建login.html 注意: springboot项目默认可以访问resources/resources, resources/s ...
- flutter中的列表组件
列表布局是我们项目开发中最常用的一种布局方式.Flutter 中我们可以通过 ListView 来定义列表项,支持垂直和水平方向展示.通过一个属性就可以控制列表的显示方向.列表有以下分类: 垂直列表 ...
- Spring Boot学习一之Spring Beans和依赖注入
你可以自由地使用任何标准的Spring框架技术去定义beans和它们注入的依赖.简单起见,我们经常使用 @ComponentScan 注解搜索beans,并结合 @Autowired 构造器注入. 如 ...
- 转载:AWR介绍使用
转载自 http://www.cnblogs.com/lanzi/archive/2011/03/07/1975096.html 自动工作负载库(Automatic Workload Reposito ...
- jquery 合并两个 json 对象
jQuery.extend( [ deep ], target, object1, [ objectN ] )合并对象到第一个对象 //deep为boolean类型,其它参数为object类型 var ...
- 用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 工厂模式 使用工厂方法 Factory Method 创建 app 对 ...
- [题解]Print a 1337-string...-数学(codeforces 1202D)
题目链接:https://codeforces.com/problemset/problem/1202/D 题意: 构造一串只由 ‘1’,‘3’,‘7’ 组成的字符串,使其 ‘1337’ 子序列数量为 ...
- 爬取拉钩网上所有的python职位
# 2.爬取拉钩网上的所有python职位. from urllib import request,parse import json,random def user_agent(page): #浏览 ...
- pandas相关操作
import pandas as pd import numpy as np ''' 一.创建df 1.定义df :传递字典 1.1每一列的名称作为键 每个键都有一个数组作为值[key:数组] 1.2 ...