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 时 ...
随机推荐
- Python3.5-20190504-自我笔记浅拷贝和深拷贝
浅拷贝和深拷贝 (自己一直搞不懂的) 1.直接赋值(把一个变量直接赋值给另一个变量),他们指向同一个内存的数据(右边的图不知道怎么画,就直接截图过来了.将就看看) ------------- 2.使用 ...
- python+selenium自动化框架搭建
环境及使用软件信息 python 3 selenium 3.13.0 xlrd 1.1.0 chromedriver HTMLTestRunner 说明: selenium/xlrd只需要再pytho ...
- linux学习-用户组与权限管理
一.用户与组 1.用户 管理员:root,UID为0 普通用户:1-60000 自动分配 系统用户:1-499,1-999(Centos7),对守护进程分配获取资源进行权限分配 登录用户:500+,1 ...
- <三剑客> 老三:grep命令用法
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正 ...
- ansible控制winserver笔记
原文地址: https://www.cnblogs.com/kingleft/p/6391652.html 环境描述: ansible控制远程windows .系统必须是sp1 .安装framewor ...
- php 统计每天价格,货币种类,汇总得算法和数据处理 (后端和前段实现自动统计价格和币种类型)
整体实现逻辑介绍 1.对查询数据做一个总体查询,需要根据查询自己主要业务逻辑数据. 2.对总体查询数据和时间和币种类型做三部分数据处理. 3.总体查询数据按照币种和日期组装二维数据对应得键值是价格. ...
- sudo su 和sudo -s的区别
sudo su 和 sudo -s都是切换到root用户,不同的是: sudo su 环境用的是目标用户(root)的环境 sudo -s 环境用的是当前用户本身的环境
- spring cloud gateway 拦截request Body
在接入Spring-Cloud-Gateway时,可能有需求进行缓存Json-Body数据或者Form-Urlencoded数据的情况. 由于Spring-Cloud-Gateway是以WebFlux ...
- 关于之前提到的python开发restful风格的接口
此处不做详细说明. https://gitee.com/alin2017/my-i-demo.git 附上git地址,有兴趣的可以去clone一下. 里面针对代码都有相应的注释, 对于每一个文件也有r ...
- How to show out three rows from the same databand On A4?
How to show out three rows from the same databand On A4? Quote Post by DoraHuang » Tue Mar 13, 2018 ...