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_1286找新朋友(欧拉定理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1286 找新朋友 Time Limit: 2000/1000 MS (Java/Others) M ...
- PHP安全之webshell和后门检测
基于PHP的应用面临着各种各样的攻击: XSS:对PHP的Web应用而言,跨站脚本是一个易受攻击的点.攻击者可以利用它盗取用户信息.你可以配置Apache,或是写更安全的PHP代码(验证所有用户输入) ...
- .31-浅析webpack源码之doResolve事件流(2)
放个流程图: 这里也放一下request对象内容,这节完事后如下(把vue-cli的package.json也复制过来了): /* { context: { issuer: '', compiler: ...
- HTTP的请求方法OPTIONS
HTTP请求方法并不是只有GET和POST,只是最常用的.据RFC2616标准(现行的HTTP/1.1)得知,通常有以下8种方法:OPTIONS.GET.HEAD.POST.PUT.DELETE.TR ...
- 数组的创建和各种API
数组的创建方式: 1. 数组直接量 var arr = [] // 创建一个空数组 var arr = [1,2,3,4] // 创建同时初始化元素 2. 实例化对象 var arr=new Arra ...
- Java读书推荐
想要深入掌握一门技术,读书是必不可少的一步,也是最重要的一步.有些书需要读很多遍才能深入理解,经过几本甚至几十本书的熏陶,才能让你在这个行业中越走越远,爱上这个行业,抽出时间多读本书吧,读书会让人如虎 ...
- Java泛型类和泛型方法
java编程思想说道: 泛型类是应用在整个类上,但同时可以在类中包含参数化方法,而这个方法所在的类可以是泛型,也可以不是泛型,也就是说是否有泛型方法,与其所在的类是否是泛型类没有关系. 泛型方法是的该 ...
- 直接请求转发(Forward)和间接请求转发(Redirect)两种区别?
用户向服务器发送了一次HTTP请求,该请求肯能会经过多个信息资源处理以后才返回给用户,各个信息资源使用请求转发机制相互转发请求,但是用户是感觉不到请求转发的.根据转发方式的不同,可以区分为直接请求转发 ...
- properties文件中中文不能显示或者中文乱码
1.properties 文件中文乱码问题 鼠标“右击”文件 => Resource => Text file encoding => UTF-8 2.properties 文件解析 ...
- C/C++ typedef
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...