明明可以用二维数点来做啊,网上为什么都是树剖+线段树呢 ?

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的更多相关文章

  1. 【bzoj4154】(dfs序+kd-tree)

    传送门 题意: 给出一颗以\(1\)为根的有根树,初始所有结点的颜色为\(1\). 之后有两个操作,一种是每次将距离\(a\)结点距离不超过\(l\)的所有儿子结点颜色染为\(c\):另一种是询问结点 ...

  2. [BZOJ 2819]NIM(dfs序维护树上xor值)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2819 分析: 树上的nim游戏,关键就是要判断树上的一条链的异或值是否为0 这个题目有 ...

  3. BZOJ 4034 BIT & Dfs序

    调了恒久突然发现输出优化忘记带负号了.. 就是差分树状数组维护Dfs序即可. #include <iostream> #include <cstring> #include & ...

  4. BZOJ 3083: 遥远的国度 dfs序,树链剖分,倍增

    今天再做一天树的题目,明天要开始专攻图论了.做图论十几天之后再把字符串搞搞,区域赛前再把计几看看. 3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 ...

  5. BZOJ 2819: Nim dfs序维护树状数组,倍增

    1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家.2.把堆v中的石子数变为k. 分析: ...

  6. BZOJ 1103 大都市(dfs序+树状数组)

    应该是一道很水的题吧... 显然可以用树链剖分解决这个问题,虽然不知道多一个log会不会T.但是由于问题的特殊性. 每次修改都是将边权为1的边修改为0,且询问的是点i到根节点的路径长度. 令点i到根节 ...

  7. bzoj 2238 Mst —— 树剖+mn标记永久化

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 看了半天... 首先,想要知道每条边删除之后的替代中最小的那个: 反过来看,每条不在 ...

  8. bzoj 2238 Mst

    显然先求出最小生成树 如果删的是非树边就不用管,还是能取最小生成树 如果删的是树边就有非树边可以替代它 反向考虑,每条非树边可以替代最小生成树上一条路径的边 所以树剖加线段树,对每条非树边在树上更新对 ...

  9. bzoj 2238 Mst——树链剖分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2238 一条非树边可以对一条链的树边产生影响.注意是边,所以把边下放到点上,只要跳 top 时 ...

随机推荐

  1. torchvision.transforms模块介绍

    torchvision.transforms模块 官网地址:https://pytorch.org/docs/stable/torchvision/transforms.html# torchvisi ...

  2. websock(AMQ)通信-前端

    服务端和客户端之间的通信 前端开发经常会依赖后端,那么如果后端服务器还没做好推送服务器,那么前端该如何呢.最简单的就是自己模拟一个服务器,用node来搭建,这边只简单介绍搭建的过程 node搭建服务器 ...

  3. python基础:4.请至少列举5个 PEP8 规范(越多越好)。

    1.变量命名规则: 不能与关键字重名,必须以数字字母下划线组成,且不能以数字开头 2.导包规则: # 推荐这样写 import random import sys # 不推荐这样写 import ra ...

  4. python 绘制三国人物关系图

    author:weizhendong data:2019.12.19 func:绘制三国演义人物关系图 """ import codecs import jieba.po ...

  5. spring+springMVC+mybatis框架整合——配置文件说明

    如下图 web.xml配置说明: spring配置文件说明-1: spring配置文件说明-2: spring配置助记:  扫注(base) 读配(loc) 数据源(和comb(使用c3p0数据源)) ...

  6. Java Web学习总结(6)Cookie/Session

    一.会话的概念 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 二.会话过程中要解决的一些问题 每个用户在使用浏览器与服务器进行 ...

  7. PHP curl_errno函数

    curl_errno — 返回最后一次的错误号 说明 int curl_errno ( resource $ch ) 返回最后一次cURL操作的错误号. 参数 ch 由 curl_init() 返回的 ...

  8. 第一次用angularJS做后台管理点滴

    很早以前就大概看过一点angualrjs,但是没有项目,一直没有进行下去,就是干巴巴的看着,过了一段时间发现什么也不记得了. 来yulebaby我的第一个后台管理是用easyui做的,做完那个以后发现 ...

  9. flutter动态列表

    在前面一篇总结flutter里面的列表组件ListView的时候,一直都是使用的静态数据,但是在实际的运用过程中,数据都是从后台获取的动态数据,不能再像前面那样写静态数据了,下面模拟一下如果使用动态数 ...

  10. truncate与delete删除数据的区别