题面

弱化版:luogu
强制在线版:bzoj

题解

本题有两种解法

离线算法:线段树合并

先看一道简单题[USACO18JAN]MooTube

本题就是在此基础上求第\(k\)高的点

首先把询问和路径都排一下序

然后记一个指针,如果当前路径可以对这个询问有贡献,就加入这条边

本题也是一样

在此基础上,线段树合并即可求第\(k\)高的点

Code

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
const int N = 1e5+10, M = 5e5+10;
int h[N];struct node {int a, b, c, id;bool operator < (const node & z) const {return c < z.c;}
}e[M], Q[M];struct ST_tree {int ls, rs, v;
}t[N*20];
int root[N], tot;void insert(int &now, int l, int r, int k) {if (!now) now = ++tot;t[now].v++;if (l == r) return;int mid = (l + r) >> 1;if (k <= mid) insert(t[now].ls, l, mid, k);else insert(t[now].rs, mid+1, r, k);
}int query(int rt, int l, int r, int k) {if (l == r) return l;int mid = (l + r) >> 1, cnt = t[t[rt].ls].v;if (k <= cnt) return query(t[rt].ls, l, mid, k);return query(t[rt].rs, mid+1, r, k-cnt);
}
int fa[N], siz[N];
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);
}int o[N], len, ans[M];int Merge(int x, int y) {if (!x || !y) return x+y;t[x].v += t[y].v;t[x].ls = Merge(t[x].ls, t[y].ls);t[x].rs = Merge(t[x].rs, t[y].rs);return x;
}void merge(int x, int y) {x = find(x); y = find(y);if (x == y) return ;fa[y] = x;root[x] = Merge(root[x], root[y]);      siz[x] += siz[y];
}int main() {int n, m, q, p = 1;read(n), read(m), read(q);for (int i = 1; i <= n; i++) read(h[i]), fa[i] = i, o[i] = h[i], siz[i] = 1;sort(o+1, o+1+n);len = unique(o+1, o+1+n) - o - 1;for (int i = 1; i <= n; i++) {      h[i] = lower_bound(o+1, o+1+len, h[i]) - o;insert(root[i], 1, len, h[i]);}for (int i = 1; i <= m; i++)read(e[i].a), read(e[i].b), read(e[i].c);for (int i = 1; i <= q; i++)read(Q[i].a), read(Q[i].c), read(Q[i].b), Q[i].id = i;sort(e+1, e+1+m);sort(Q+1, Q+1+q);
/*  for (int i = 1; i <= q; i++)printf("%d %d %d\n", Q[i].a, Q[i].b, Q[i].c);*/for (int i = 1; i <= q; i++) {while (p <= m && e[p].c <= Q[i].c) merge(e[p].a, e[p].b), p++;if (siz[find(Q[i].a)] < Q[i].b) ans[Q[i].id] = -1;else ans[Q[i].id] = o[query(root[find(Q[i].a)], 1, len, siz[find(Q[i].a)]-Q[i].b+1)];}for (int i = 1; i <= q; i++)printf("%d\n", ans[i]);return 0;
}

在线算法:主席树+Kruskal重构树

一开始以为加强版是数据加强..

Kruskal重构树

满足堆的性质

所以我们可以倍增找到最大的小于等于一个权值的点
然后它的子树里的所有点都可以互相到达

求第\(k\)大的点,在\(dfs\)序上主席树即可

Code

#include<bits/stdc++.h>#define LL long long
#define RG registerusing namespace std;
template<class T> inline void read(T &x) {x = 0; RG char c = getchar(); bool f = 0;while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();x = f ? -x : x;return ;
}
template<class T> inline void write(T x) {if (!x) {putchar(48);return ;}if (x < 0) x = -x, putchar('-');int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
const int N = 2e5+10, M = 5e5+10;
int n, m, q, h[N];struct Edge {int u, v, w;bool operator < (const Edge &z) const {return w < z.w;}
}e[M];int fa[N], val[N], tot;
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);
}
struct node {int to, nxt;
}g[N];
int last[N], gl;
void add(int x, int y) {g[++gl] = (node) {y, last[x]};last[x] = gl;
}void kruskal() {sort(e+1, e+1+m);for (int i = 1; i <= n; i++)fa[i] = i;int cnt = 0;for (int i = 1; i <= m; i++) {int u = e[i].u, v = e[i].v, w = e[i].w;u = find(u), v = find(v);if (u == v) continue;h[++tot] = w;add(tot, u), add(tot, v);fa[u] = fa[v] = fa[tot] = tot;if (++cnt == n-1) break;}return ;
}int dfn[N], cnt, l[N], r[N];
int anc[N][21];void dfs(int u) {if (u <= n)dfn[++cnt] = h[u];l[u] = cnt;for (int i = 1; i <= 20; i++)anc[u][i] = anc[anc[u][i-1]][i-1];for (int i = last[u]; i; i = g[i].nxt) {int v = g[i].to;anc[v][0] = u;dfs(v);}r[u] = cnt;return ;
}
int o[N];struct Tree {struct node {int ls, rs, v;}t[N*20];int cnt, root[N];void insert(int &now, int l, int r, int pos) {t[++cnt] = t[now];now = cnt;t[now].v++;if (l == r) return ;int mid = (l + r) >> 1;if (pos <= mid) insert(t[now].ls, l, mid, pos);else insert(t[now].rs, mid+1, r, pos);}int query(int rt1, int rt2, int l, int r, int k) {if (l == r) return l;int mid = (l + r) >> 1, tmp = t[t[rt2].ls].v - t[t[rt1].ls].v;if (tmp < k) return query(t[rt1].rs, t[rt2].rs, mid+1, r, k-tmp);else return query(t[rt1].ls, t[rt2].ls, l, mid, k);}
}T;int main() {read(n), read(m), read(q);tot = n;for (int i = 1; i <= n; i++) read(h[i]), o[i] = h[i];for (int i = 1; i <= m; i++) read(e[i].u), read(e[i].v), read(e[i].w);kruskal();dfs(tot);sort(o+1, o+1+n);int K = unique(o+1, o+1+n) - o - 1;for (int i = 1; i <= n; i++)dfn[i] = lower_bound(o+1, o+1+K, dfn[i]) - o;int ans = 0;for (int i = 1; i <= n; i++) {T.root[i] = T.root[i-1];T.insert(T.root[i], 1, K, dfn[i]);}h[0] = 2147483647;while (q--) {if (ans == -1) ans = 0;int v, x, k; read(v), read(x), read(k);v ^= ans, x ^= ans, k ^= ans;for (int i = 20; i >= 0; i--)if (h[anc[v][i]] <= x) v = anc[v][i];if (r[v] - l[v] < k) ans = -1;else ans = o[T.query(T.root[l[v]], T.root[r[v]], 1, K, r[v]-l[v]+1-k)];write(ans); putchar('\n');}return 0;
}

转载于:https://www.cnblogs.com/zzy2005/p/10319754.html

ONTAK2010 Peaks加强版(离线在线)相关推荐

  1. #3551. [ONTAK2010]Peaks加强版(kruskal 重构树 + 主席树)

    #3551. [ONTAK2010]Peaks加强版 我们要求从一个点出发经过困难值小于等于xxx的路径所能到达的山峰中第kkk高的是什么. 考虑按照边权升序,建议kruskalkruskalkrus ...

  2. BZOJ.3551. [ONTAK2010]Peaks加强版

    传送门 类似可以离线处理的题目Peaks KruskalKruskalKruskal重构树 强制在线,主要就考一个[重构树]以及[树链剖分]+[静态区间第K大],离散化建立一颗权值线段树即可 重构树的 ...

  3. bzoj3551: [ONTAK2010]Peaks加强版

    很明显只有最小生成树里面的点有用 我会一个离线的做法,把询问边长排序,逐步合并树,启发式合并splay 在线怎么做呢? 考虑合并出最小生成树的过程,两点合并是并不是一边连向一边而是建出新点,并将新点连 ...

  4. [ONTAK2010] Peaks加强版 (kruskal重构树+主席树+倍增)

    Peaks description solution code description 在Bytemountains有N座山峰,每座山峰有他的高度h_i 有些山峰之间有双向道路相连,共M条路径,每条路 ...

  5. P7834 [ONTAK2010] Peaks 加强版

    传送门 题目大意 感觉题目描述已经足够清楚了. Solution 这道题需要的东西有点多,我们不妨先来分解一下题目的需求. 经过权值 ≤ x \le x ≤x 的边所能到达的点. 马上想到最小生成树, ...

  6. bzoj3551 [ONTAK2010]Peaks加强版 kruskal重构树

    最大边最小,就是最小生成树,可以考虑用主席树维护father数组,但不能遍历子集查找 然后就只能牺牲一部分空间时间来多存一些东西 多存的就是边值大小顺序,本来以为是用主席树排边值,结果由于此题有2种数 ...

  7. [BZOJ3545][ONTAK2010]Peaks

    [BZOJ3545][ONTAK2010]Peaks 试题描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越 ...

  8. Tableau使用教程:如何Tableau中添加离线/在线地图

    Tableau使用教程:如何Tableau中添加离线/在线地图 发布时间:2019-04-03 版权: 相关软件:BIGEMAP GIS Office软件 BIGEMAP可以提供Tableau多样化的 ...

  9. IOS音视频(四十六)离线在线语音识别方案

    IOS音视频(四十六)离线在线语音识别方案 IOS音视频(四十六)离线在线语音识别方案 方案一:Siri语音识别 Siri语音识别简介 Siri语音识别功能类介绍 Siri语音识别功能集成 方案二:百 ...

最新文章

  1. 存储过程与事务应用两三事
  2. java,将Image变量保存成图片
  3. LAMP攻略: LAMP环境搭建,Linux下Apache,MySQL,PHP安装与配置
  4. html教程padding,HTML CSS——margin和padding的学习
  5. jQuery 设计和自定义一个带展开动画效果的导航栏
  6. java获取正在执行的timer_Java线程与并行编程(一)
  7. 设计模式17_命令模式
  8. Tomcat启动过程(一):从BootStrap到EndPonit
  9. c#对输入的字符串加密
  10. 流浪宠物管理系统-基于SSM
  11. ip数据库java,java实现对纯真IP数据库的查询
  12. 自学前端的日子,记录我的秃头之旅
  13. 华三服务器管理口地址_H3C服务器配置HDM远程管理系统
  14. linux+h264+cpu编码,Linux下使用MPV+SMPlayer播放HEVC H265编码视频
  15. LDC1314和LDC1312的使用
  16. 各位大神,有没有类似于百度云软件开始时的设置向导的例子呀
  17. 网页简单整合Skype
  18. 续编-联想原装系统OEM系统联想出厂系统联想原装系统Lenovo ThinkPad ThinkBook出厂预装系统原厂系统
  19. 怎么制作公司网页教程【网站制作】
  20. 从零搭建Spring Boot脚手架:开篇以及技术选型1

热门文章

  1. Hibernate中自动生成数据库表的两种方式
  2. Hbase常用操作(增删改查)
  3. 不该被遗忘的nodeName、nodeValue和nodeType!
  4. 问题解决:SqlParameterCollection只接受非空的SqlParameter类型对象,不接受SqlParameter[]对象
  5. 字典树(trie树)、后缀树
  6. 构建自己的C/C++插件开发框架
  7. linux命令telnet
  8. 编译时“-nostdlib”的使用
  9. 内存如何分配和如何释放?
  10. QT5中实现多窗口切换,并从子窗口返回数据