BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增
建出来 $Kruskal$ 重构树.
将询问点向上跳到深度最小,且合法的节点上.
那么,得益于重构树优美的性质,这个最终跳到的点为根的所有子节点都可以与询问点互达.
对于子树中求点权第 $k$ 大的问题,直接对 $dfs$ 序建主席树即可.
#include <cstdio>
#include <algorithm>
#define N 200005
#define M 500002
#define inf 1000000000
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
namespace IO {
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
};
int h[N],rt[N],n,m,Q;
struct Edge {
int u,v,c;
}e[M];
bool cmp(Edge a,Edge b) {
return a.c<b.c;
}
namespace seg {
#define ls t[now].lson
#define rs t[now].rson
struct Node {
int lson,rson,sum;
}t[N*30];
int tot;
void update(int pre,int &now,int l,int r,int p) {
now=++tot;
t[now]=t[pre];
++t[now].sum;
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) update(t[pre].lson,ls,l,mid,p);
else update(t[pre].rson,rs,mid+1,r,p);
}
int kth(int rt1,int rt2,int l,int r,int k) {
if(t[rt2].sum-t[rt1].sum==0) return 0;
if(l==r) return l;
int mid=(l+r)>>1,rsize=t[t[rt2].rson].sum-t[t[rt1].rson].sum;
if(k<=rsize) return kth(t[rt1].rson,t[rt2].rson,mid+1,r,k);
else return kth(t[rt1].lson,t[rt2].lson,l,mid,k-rsize);
}
#undef ls
#undef rs
};
namespace tree {
int tot,edges,tim;
int p[N],maxv[N],hd[N],to[N],nex[N],fa[22][N],F[22][N],dfn[N],size[N],dot[N];
void init() {
for(int i=1;i<=n;++i) p[i]=i;
}
int find(int x) {
return p[x]==x?x:p[x]=find(p[x]);
}
void addedge(int u,int v) {
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs(int u,int ff) {
int i,j;
dfn[u]=++tim,dot[tim]=u,size[u]=1;
fa[0][u]=ff, F[0][u]=max(maxv[u],maxv[ff]);
for(i=1;i<=20;++i) {
fa[i][u]=fa[i-1][fa[i-1][u]];
F[i][u]=max(F[i-1][u], F[i-1][fa[i-1][u]]);
}
for(i=hd[u];i;i=nex[i]) dfs(to[i],u),size[u]+=size[to[i]];
}
// 找到最后一个小的等于 k 的点
int get(int x,int k) {
for(int i=20;i>=0;--i)
if(fa[i][x]&&F[i][x]<=k) x=fa[i][x];
return x;
}
void build() {
init();
sort(e+1,e+1+m,cmp);
tot=n;
for(int i=1;i<=m;++i) {
int u=e[i].u,v=e[i].v,c=e[i].c,x,y;
x=find(u),y=find(v);
if(x!=y) {
++tot;
p[x]=p[y]=p[tot]=tot;
maxv[tot]=c;
addedge(tot,x),addedge(tot,y);
}
}
dfs(tot,0);
for(int i=1;i<=tim;++i) {
if(dot[i]>n) rt[i]=rt[i-1];
else seg::update(rt[i-1],rt[i],0,inf,h[dot[i]]);
// printf("%d %d\n",i,h[dot[i]]);
}
}
};
int main() {
int i,j;
// setIO("input");
using namespace IO;
n=rd(),m=rd(),Q=rd();
for(i=1;i<=n;++i) h[i]=rd();
for(i=1;i<=m;++i) e[i].u=rd(),e[i].v=rd(),e[i].c=rd();
tree::build();
int lastans=0;
for(i=1;i<=Q;++i) {
int v,x,k;
v=rd(),x=rd(),k=rd();
if(lastans!=-1) {
v^=lastans;
x^=lastans;
k^=lastans;
}
int p=tree::get(v,x);
int l=tree::dfn[p], r=tree::dfn[p]+tree::size[p]-1;
int re=seg::kth(rt[l-1],rt[r],0,inf,k);
printf("%d\n",re?re:-1);
lastans=re;
}
return 0;
}
BZOJ 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+dfs序+主席树+倍增的更多相关文章
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
- BZOJ.3551.[ONTAK2010]Peaks加强版(Kruskal重构树 主席树)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. 强制在线. \ ...
- 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重构树+树上倍增+主席树
这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,L ...
- 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)
传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...
- 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个 ...
随机推荐
- PTA(Basic Level)1024.科学计数法
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指 ...
- DOS sqlcmd
C:\>sqlcmd -? Microsoft (R) SQL Server 命令行工具版本 12.0.2000.8 NT版权所有 (c) 2014 Microsoft.保留所有权利. 用法: ...
- Docker守护进程
Docker安装完成之后, 需要确定Docker的守护进程是否已经运行. Docker是使用root 权限运行他的程序,进而可以处理普通用户无法完成的操作(比如挂载文件系统). docker程序是Do ...
- Idea导入Eclipse的Web项目并部署到Tomcat
⒈启动Idea,选择导入项目 选择导入的项目路径后,选择项目类型后一路next即可. ⒉选择File->Project Structure打开项目配置窗口(ctrl + alt + shift ...
- P1816忠诚
这是一个区间查询最值的问题,用线段树来做. 建树的时候,这里不是求和,应该是e[k].w=min(e[k*2].w,e[k*2+1].w),所以这里要注意以下,其次是查询的时候,因为本题不用让我们修改 ...
- file_put_contents实现内容追加
file_put_contents("test.txt", "This is another something.", FILE_APPEND); FILE_A ...
- 2019年8月23日 星期五(韩天峰的swoole)
Swoole:面向生产环境的 PHP 异步网络通信引擎 使 PHP 开发人员可以编写高性能的异步并发 TCP.UDP.Unix Socket.HTTP,WebSocket 服务. Swoole 可以广 ...
- win10操作系统的安装
电脑被重装操作系统了,一切从头开始啦!!! 不过倒是学习了,给大家分享一些学习经验~ 1:制作启动盘 制作启动盘的首先要准备一个空的U盘,为什么说空的呢,因为制作的时候会格式化U盘,只能存个操作系统, ...
- Ubuntu分区挂载
创建主分区: 25G 主分区 空间起始位置 Ext4日志文件系统 / (ps:安装主要放这了,原因不明) 创建swap分区: 8192MB 逻辑分区 空间起 ...
- javascript--获取一个页面各个标签的数量
获取一个页面各个标签的数量 document.getElementsByTagName('*')--获取所有的标签. var obj = document.getElementsByTagName(' ...