3551: [ONTAK2010]Peaks加强版
题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线
PoPoQQQ大爷题解传送门
说一下感受:
容易发现一定选最小生成树上的边,然后用到了一个神奇的东西
Kruskal重构树
- 进行Kruskal过程中,每条边用一个点代替,左右儿子分别是连的两个点的当前的父亲
这样就形成了一棵树,叶子都是原图上的点,其他都是原图上的边 - 深度越小的点对应的边权值越大
- 两点路径上的权值不变
- 这样的话,与一个点通过权值\(\le lim\)的边连通,就是这个点权值\(\le lim\)的父亲对应的子树中的点
对dfs序建主席树就行了
实现上我只将原图中的点加入了dfs序
该死离散化写错了WA了半小时
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define lc(x) t[x].l
#define rc(x) t[x].r
const int N=2e5+5, M=5e5+5;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int n, m, Q, val[N], tot, u, lim, k, mp[N];
struct meow{
int u,v,w;
bool operator <(const meow &r) const{return w<r.w;}
}a[M];
namespace ufs{
int fa[N];
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
}
struct edge{int v,ne;}e[N<<1];
int cnt, h[N];
inline void ins(int u, int v) {
e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
}
void Kruskal() {
using ufs::fa; using ufs::find;
sort(a+1, a+1+m);
int cnt=0;
for(int i=1; i<=m; i++) {
int u=a[i].u, v=a[i].v, w=a[i].w;
int x=find(u), y=find(v);
if(x==y) continue;
val[++tot]=w; //printf("hey %d %d %d %d\n",x,y,tot,val[tot]);
ins(tot, x); ins(tot, y);
fa[x]=fa[y]=fa[tot]=tot;
if(++cnt == n-1) break;
}
}
int deep[N], dfc, ver[N], L[N], R[N];
int fa[N][20];
void dfs(int u) { //printf("dfs %d %d\n",u,val[u]);
if(u<=n) ver[++dfc]=u;
L[u]=dfc;
for(int i=1; (1<<i)<=deep[u]; i++)
fa[u][i] = fa[ fa[u][i-1] ][i-1];
for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa[u][0]) {
fa[e[i].v][0]=u;
deep[e[i].v]=deep[u]+1;
dfs(e[i].v);
}
R[u]=dfc;
}
struct ChairTree{
struct meow{int l,r,size;}t[N*30];
int sz, root[N];
void insert(int &x, int l, int r, int p) {
t[++sz]=t[x]; x=sz;
t[x].size++;
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) insert(t[x].l, l, mid, p);
else insert(t[x].r, mid+1, r, p);
}
void build() {
for(int i=1; i<=n; i++) root[i]=root[i-1], insert(root[i], 1, *mp, val[ver[i]]);// printf("%d ",ver[i]);puts("");
}
int kth(int x, int y, int k) { //printf("kth %d %d %d\n",x,y,k);
x=root[x]; y=root[y];
int all = t[y].size-t[x].size; //printf("xy %d %d %d\n",x,y,all);
if(k>all) return -1;
k = all-k+1;
int l=1, r=*mp;
while(l!=r) {
int lsize = t[lc(y)].size - t[lc(x)].size, mid=(l+r)>>1;
if(k<=lsize) x=lc(x), y=lc(y), r=mid;
else x=rc(x), y=rc(y), l=mid+1, k-=lsize;
}
return l;
}
}C;
int main() {
freopen("in","r",stdin);
n=read(); m=read(); Q=read(); tot=n;
for(int i=1; i<=n; i++) val[i]=mp[i]=read(), ufs::fa[i]=i;
val[0]=1e9+5;
for(int i=1; i<=m; i++) a[i].u=read(), a[i].v=read(), a[i].w=read();
Kruskal();
dfs(tot);
sort(mp+1, mp+1+n); mp[0]=unique(mp+1, mp+1+n)-mp-1;
for(int i=1; i<=n; i++) val[i] = lower_bound(mp+1, mp+1+mp[0], val[i])-mp;
C.build();
int ans=0;
for(int i=1; i<=Q; i++) {
if(ans==-1) ans=0;
u=read()^ans, lim=read()^ans, k=read()^ans;
//u=read();lim=read();k=read();
for(int i=16; i>=0; i--) if(val[fa[u][i]]<=lim) u=fa[u][i];
ans = C.kth(L[u], R[u], k);
if(ans!=-1) ans=mp[ans];
printf("%d\n",ans);
}
}
BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]的更多相关文章
-
BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增
建出来 $Kruskal$ 重构树. 将询问点向上跳到深度最小,且合法的节点上. 那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达. 对于子树中求点权第 $k$ 大的问 ...
-
【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树
bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...
-
BZOJ.3551.[ONTAK2010]Peaks加强版(Kruskal重构树 主席树)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. 强制在线. \ ...
-
【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,L ...
-
BZOJ3551 ONTAK2010Peaks加强版(kruskal重构树+dfs序+主席树)
kruskal重构树本质就是给并查集显式建树来替代可持久化并查集.将边按困难度从小到大排序后建出该树,按dfs序建主席树即可.查询时跳到深度最浅的满足在该重要度下已被合并的点,在子树内查询第k大. # ...
-
【BZOJ-3545&;3551】Peaks&;加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
-
[BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
-
bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...
-
BZOJ3551: [ONTAK2010]Peaks加强版【Kruskal重构树】【主席树】
重要的事情说三遍 不保证图联通 不保证图联通 不保证图联通 那些和我一样认为重构树是点数的童鞋是要GG Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个 ...
随机推荐
-
(视频) 《快速创建网站》3.4 网站改版3分钟搞定 - WordPress主题安装和备份
本文是<快速创建网站>系列的第8篇,如果你还没有看过之前的内容,建议你点击以下目录中的章节先阅读其他内容再回到本文. 访问本系列目录,请点击:http://devopshub.cn/tag ...
-
C,C++经典笔试题(答案)转自:http://blog.163.com/jianhuali0118@126/blog/static/377499702008230104125229/
一.请填写BOOL , float, 指针变量 与“零值”比较的 if 语句.(10分) 请写出 BOOL flag 与“零值”比较的 if 语句.(3分) 标准答案: if ( fla ...
-
gitbook使用
第一步:安装node.js 官方网址:https://nodejs.org/en/ 运行以下命令,确认是否安装成功 node -v 第二步:安装gitbook npm install -g gitbo ...
-
sizeof _countof _tcslen的比较
sizeof ----用于计算数组或其他对象的大小,以字节为单位,含\0结束符. _countof----一个宏,用于计算数组的实际元素个数 ,含\0结束符: _tcslen----c++求数组长度的 ...
-
Java用链表实现栈和队列
1.用链表实现栈 package stack; /** * * @author denghb * */ class Link { public long dData; public Link next ...
-
python 安装PyV8 和 lxml
近来在玩python爬虫,需要使用PyV8模块和lxml模块.但是执行pip install xx 或者easy_install xx 指令都会提示一些错误.这些错误有些是提示pip版本过低或者缺少v ...
-
nexus搭建
Nexus是Maven仓库管理软件,可以用来搭建私服.主页 http://www.sonatype.org/nexus/ 下载地址 http://www.sonatype.org/nexus/down ...
-
笔记整理--Linux多线程
Unix高级环境编程系列笔记 (2013/11/17 14:26:38) Unix高级环境编程系列笔记 出处信息 通过这篇文字,您将能够解答如下问题: 如何来标识一个线程? 如何创建一个新线程? 如何 ...
-
ZooKeeper 学习笔记
ZooKeeper学习笔记 1. zookeeper基本概念 zookeeper是一个分布式的,开放源码的分布式应用程序协调服务,是hadoop和Habase的重要组件,是为分布式应用提供一致性服 ...
-
蚂蚁金服安全实验室首次同时亮相BlackHat Asia 以及CanSecWest国际安全舞台
近期,蚂蚁金服巴斯光年安全实验室(以下简称AFLSLab)同时中稿BlackHat Asia黑帽大会的文章以及武器库,同时在北美的CanSecWest安全攻防峰会上首次中稿Android安全领域的漏洞 ...