题面

弱化版:luogu

强制在线版:bzoj

题解

本题有两种解法

离线算法:线段树合并

先看一道简单题[USACO18JAN]MooTube

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

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

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

本题也是一样

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

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register using 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 register using 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;
}

ONTAK2010 Peaks加强版(离线&在线)的更多相关文章

  1. 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树

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

  2. BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]

    3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...

  3. [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)

    3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2438  Solved: 763[Submit][ ...

  4. [ONTAK2010] Peaks 加强版

    [ONTAK2010] Peaks 加强版 题目大意:原题变为强制在线查询 Solution 读入山高,排序后依然建立树链,初始化并查集,初始化重构树新节点标号为\(n+1\) 读入边,按照边权从小到 ...

  5. 【BZOJ3551】 [ONTAK2010]Peaks加强版

    BZOJ3551 [ONTAK2010]Peaks加强版 Solution Kruscal重构树后发现可以对于小于的离散化然后倍增+主席树找到上一个的可行解. 然后就可以了. 如果数组开的不好,容易在 ...

  6. 3551: [ONTAK2010]Peaks加强版

    3551: [ONTAK2010]Peaks加强版 https://www.lydsy.com/JudgeOnline/problem.php?id=3551 分析: kruskal重构树 +  倍增 ...

  7. bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Stat ...

  8. BZOJ3551 : [ONTAK2010]Peaks加强版

    首先强制在线的话,肯定是不能再离线排序+平衡树启发式合并了. 这回要用的是线段树合并,每次把两棵线段树合并,总复杂度为$O(n\log n)$ 预处理: 把边按权值从小到大排序,依次加边, 对于边(x ...

  9. 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树

    bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...

随机推荐

  1. code1047 邮票面值设计

    dfs+dp dfs枚举每种情况,每层递归确定第k个数i:i = a[k-1]+1 to a[k-1]*n+1 当枚举完一个序列时,使用check()测试它能达到的max 使用dp.设dp[i]为凑成 ...

  2. JSON Web Token(JWT)学习笔记

    1.JWT 的Token 标准的Token由三个部分并以.(点号)连接方式组成,即 header.payload.signature,如下 eyJhbGciOiJIUzI1NiIsInR5cCI6Ik ...

  3. ES5、6、7浅析

    ECMA Script 它是一种由ECMA组织(前身为欧洲计算机制造商协会)制定和发布的脚本语言规范 而我们学的JavaScript是ECMA的实现, 但术语ECMAScript和JavaScript ...

  4. Qt5.3.1,的linux平台体验之旅

    1. samba安装:http://blog.csdn.net/voice_shen/article/details/7692605 2. 安装run,  sudo chmod 777 filenam ...

  5. 可排序的 COMB 类型 GUID

    最新代码在这儿:CombGuid.cs 首先这里不做GUID与整形作为主键的优劣之争,GUID自有它优势,但GUID本身是乱序的,会对索引的维护带来性能上的损耗,数据量越大越明显. COMB 类型 G ...

  6. [转载]Java线程的两种实现方式

    转载:http://baijiahao.baidu.com/s?id=1602265641578157555&wfr=spider&for=pc 前言 线程是程序的一条执行线索,执行路 ...

  7. Python之set集合与collections系列

    1>set集合:是一个无序且不重复的元素集合:访问速度快,解决了重复的问题: s2 = set(["che","liu","haha" ...

  8. ibatis源码学习3_源码包结构

    ibatis的技术是从xml里面字符串转换成JAVA对象,对象填充JDBC的statement查询,然后从resultset取对象返回,另外利用ThreadLocal实现线程安全,JDBC保证了事务控 ...

  9. nginx中级应用-续

    1.server下配置的每个location,都需要有自己的一套代理配置 即要么加入: root  某个目录 要么加入 proxy_pass 某个地址;  proxy_redirect off; # ...

  10. sqlite数据库的char,varchar,text,nchar,nvarchar,ntext的区别(转)

    sqlite数据库存储table1.CHAR.CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间,不 ...