BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
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个 ...
随机推荐
- hdu_1012(水题。。。不能再水)
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...
- RAID 详解
一.什么是RAID 磁盘阵列全名是『Redundant Arrays of Inexpensive Disks, RAID 』,英翻中的意思是:容错式廉价磁盘阵列. RAID 可以透过一个技术(软件或 ...
- [国嵌攻略][164][USB驱动程序设计]
USB驱动模型 1.USB host controller driver(主控器驱动):为USB主控制器提供驱动程序 2.USB core(USB核心):连接USB主控制器驱动和USB设备驱动 3.U ...
- Android回顾系列——之HttpUrlConnect的使用
写在前面: 最近准备一个关于Android的比赛.由于赛项要求,不得使用第三方工具.框架:故最近来温习一下Google官方提供的原始API的使用. 说实话,用惯了第三方的库,再回过头来用原生的api的 ...
- Android开发之漫漫长途 XII——Fragment详解
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- 解决mysql不是内部或外部命令
安装Mysql后,当我们在cmd中敲入mysql时会出现'Mysql'不是内部或外部命令,也不是可运行的程序或其处理文件. 工具/原料 mysql cmd 方法/步骤 1 打开我的电脑在我的电脑右键中 ...
- DEDECMS 留言薄模块的使用方法
一.留言薄的安装 留言薄的安装过程和其他插件一样,首先我们进入后台模块管理列表,点击其对应的"安装": 以上步骤,我们完成了留言薄插件的安装. 二.留言薄的卸载 留言薄的卸载,同样 ...
- c#目录以及子目录下图片批量缩放,像素不变,图像大小改变
采用多线程,整体效果 图像根目录黏贴或者手工选择,点击开始,进行目录底下图片筛查.采用多线程,点击开始按钮,开启线程,这样UI不会卡住 private void button2_Click(objec ...
- kafka学习
kafka名词解释和工作方式: Producer :消息生产者,就是向kafka broker发消息的客户端. Consumer :消息消费者,向kafka broker取消息的客户端 Topic : ...
- 查阅API文档
Java的API文档:就一句话:应用程序接口 •API (Application Programming Interface,应用程序编程接口)是 Java 提供的基本编程接口. •Java语言提供了 ...