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个 ...
随机推荐
- A * B Problem Plus(fft)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1402 hdu_1402:A * B Problem Plus Time Limit: 2000/100 ...
- 解决jsp中编辑和删除时候弹出框闪退的问题。
---恢复内容开始--- /* 火箭设备特殊记载</li> <!-- yw4 --> */ function getYw4DL(){ var controlparm={&quo ...
- C#面试题整理(1)
最近在看CLR VIA C#,发现了一些案例很适合来做面试题.特此整理: 1,System.Object里的GetType方法是否为虚函数?说出理由. 答案:不是,因为C#是一种类型安全的语言,如果覆 ...
- Winform & Devexpress Chart使用入门
一.Chart(Winform) 使用图表控件(chart)首先要理解图表区域(ChartArea).XY轴(AxisX.AxisY).数据点(Series).标题(Title).图例(Legend) ...
- 十二个 ASP.NET Core 例子——配置操作
目录: 简单配置(利用configration 键值读取) 使用选项和配置对象(自定义类绑定配置文件实现读取) IOptionsSnapshot(配置文件更改时也变化) 内存数据放到配置对象中 实体框 ...
- Node之简单的前后端交互
node是前端必学的一门技能,我们都知道node是用的js做后端,在学习node之前我们有必要明白node是如何实现前后端交互的. 这里写了一个简单的通过原生ajax与node实现的一个交互,刚刚学n ...
- IT术语的正确读法
Linux /ˈlɪnəks/ /ˈlɪnʊks/(EU) Linux 是一类 Unix 计算机操作系统的统称.该操作系统的核心的名字也是“ Linux” .参考: < !-- m --> ...
- DALI解码模块
DALI-MOD2接口模块使用手册 一.概述(联系人:张先生,电话:13923882807,QQ:813267849) 一.概述 欢迎使用本公司的DALI解码模块,该模块支持"DALI第一套 ...
- bash中声明变量方法
bash提供了declare命令来声明变量,该命令的基本语法如下: declare attribute variable 其中,attribute表示变量的属性,常用的属性有如下所述. ...
- 一步步使用BMC Atrium Orchestrator Vmware Infrastructure Event Monitor
本教程将一步步演示怎么使用BMC Atrium Orchestrator (BAO) Vmware Infrastructure Event Monitor来监控VSphere Webservice的 ...