ONTAK2010 Peaks加强版

给一个图,每个点有点权,$q$ 次询问从 $x$ 开始只走点权小于等于 $y$ 的路径能到的点中第 $k$ 大的点权,无解输出 -1

强制在线

请注意因为这个 sb 博主为了描述方便,这里的题目描述用的字母跟原题有出入,题解跟跟这里的题目描述一样,不一定跟 bzoj 上一样(

$n \leq 10^5$

$m,q \leq 5 \times 10^5$

点权$\leq 10^9$

sol:

Kruskal 重构树,每次能走的是一个子树

于是我们可以先倍增找到能走的最高的点(倍增找到重构树上点权小于等于 $y$ 的最高的点)

之后就变成了“一个子树里第 $k$ 小的点权是多少”

我们把 dfs 序处理出来,就是一个区间第 $k$ 小

注意重构树上的 dfs 序要特殊处理一下

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
    int x = 0,f = 1;char ch = getchar();
    for(;!isdigit(ch);ch = getchar())if(ch == ‘-‘)f = -f;
    for(;isdigit(ch);ch = getchar())x = 10 * x + ch - ‘0‘;
    return x * f;
}
const int maxn = 2e5 + 10;
int n,m,q,lastans,ToT,nd;
int first[maxn],to[maxn << 1],nx[maxn << 1],val[maxn],cnt;
inline void add(int u,int v)
{
    to[++cnt] = v;
    nx[cnt] = first[u];
    first[u] = cnt;
    to[++cnt] = u;
    nx[cnt] = first[v];
    first[v] = cnt;
}
struct EDG{int u,v,w;bool operator < (const EDG &b)const{return w < b.w;}}es[maxn * 10];
int tp;
int h[maxn],rnk[maxn];
int ufs[maxn];
inline int find(int x){return x == ufs[x] ? x : ufs[x] = find(ufs[x]);}
int mn[maxn],mx[maxn],dfn,fa[maxn][23],reh[maxn];
void dfs(int x)
{
    //cout<<x<<" ";
    if(x <= n) mn[x] = mx[x] = ++dfn,reh[dfn] = x;
    else mn[x] = n + 1;
    for(int i=1;i<=20;i++)fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for(int i=first[x];i;i=nx[i])
    {
        if(to[i] == fa[x][0])continue;
        fa[to[i]][0] = x;
        dfs(to[i]);
        mn[x] = min(mn[x],mn[to[i]]);
        mx[x] = max(mx[x],mx[to[i]]);
    }
}
inline int get_val(int x,int w)
{
    for(int i=20;~i;i--)
        if(fa[x][i] && h[fa[x][i]] <= w)x = fa[x][i];
    return x;
}
int root[maxn],ls[maxn * 10],rs[maxn * 10],sum[maxn * 10],TaT;
inline void Insert(int &now,int pre,int l,int r,int pos)
{
    now = ++TaT;
    ls[now] = ls[pre];rs[now] = rs[pre];
    sum[now] = sum[pre] + 1;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(pos <= mid)Insert(ls[now],ls[pre],l,mid,pos);
    else Insert(rs[now],rs[pre],mid + 1,r,pos);
}
inline int query(int now,int pre,int l,int r,int k)
{
    //cout<<now<<" "<<pre<<" "<<l<<" "<<r<<" "<<" "<<k<<endl;
    if(sum[now] - sum[pre] < k)return -1;
    if(l == r) return l;
    int mid = (l + r) >> 1;
    if(sum[rs[now]] - sum[rs[pre]] >= k)return query(rs[now],rs[pre],mid + 1,r,k);
    else return query(ls[now],ls[pre],l,mid,k - sum[rs[now]] + sum[rs[pre]]);
}
int main()
{
    //freopen("szc10e.in","r",stdin);
    //freopen("fc.out","w",stdout);
    n = read(),m = read(),q = read();
    for(int i=1;i<=n;i++)rnk[i] = h[i] = read();
    for(int i=1;i<=n + n;i++)ufs[i] = i;
    sort(rnk + 1,rnk + n + 1);
    ToT = unique(rnk + 1,rnk + n + 1) - rnk - 1;
    for(int i=1;i<=n;i++)h[i] = lower_bound(rnk + 1,rnk + ToT + 1,h[i]) - rnk;
    for(int i=1;i<=m;i++)
    {
        int u = read(),v = read(),w = read();es[i] = (EDG){u,v,w};
    }nd = n;/*system("cls");*/sort(es + 1,es + m + 1);
    int fu,fv;
    for(int i=1;i<=m;i++)
    {
        fu = find(es[i].u),fv = find(es[i].v);
        if(fu == fv)continue;
        ++nd;h[nd] = es[i].w;
        add(nd,fu);add(nd,fv);
        ufs[fu] = ufs[fv] = nd;
    }
    //system("pause");
    dfs(nd);
    for(int i=1;i<=n;i++)
    {
        Insert(root[i],root[i - 1],1,n,h[reh[i]]);
    }
    int v,x,k,rt;
    while(q--)
    {
        v = read(),x = read(),k = read();
        if(lastans != -1)v ^= lastans,x ^= lastans,k ^= lastans;
        rt = get_val(v,x);
        lastans = query(root[mx[rt]],root[mn[rt] - 1],1,n,k);
        if(lastans != -1)lastans = rnk[lastans];
        printf("%d\n",lastans);
       // lastans = 0;
    }
}

原文地址:https://www.cnblogs.com/Kong-Ruo/p/9852786.html

时间: 2024-10-14 13:41:10

ONTAK2010 Peaks加强版的相关文章

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

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

bzoj 3551: [ONTAK2010]Peaks加强版

Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表示一组询问.v=v xor lastans,x=x xor lastans,k=k xor lastans.如果lastans=-1则不变. Output 同3545 Sample Input Sample Output HINT [数据范围]同3545 Source

bzoj3551 [ONTAK2010]Peaks加强版

Description //[题目描述]同3545 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include

bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表示一组询问.v=v xor lastans,x=x xor lastans,k=k xor lastans.如果lastans=-1则不变. Output 同3545 [思路] Kruskal+主席树+dfs序 一个叫kruskal重构树的方法QWQ.在kruskal合

BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树

题目大意:同3545 强制在线 3545题解传送门:http://blog.csdn.net/popoqqq/article/details/40660953 强制在线没法排序 启发式合并也就用不了了 Kruskal重构树是个挺好玩的东西 可以拿来处理一些最小生成树的边权最值问题 这里我们Kruskal连边时并不直接连边 而是新建一个节点ext 将两个点所在子树都连到ext的儿子上 比如说样例的树就建成了这样 图中红色的是原图的边权,黑色的是原图上的点 这样生成的树有一些十分优美的性质: 1.二

bzoj3545 [ONTAK2010]Peaks、bzoj3551 [ONTAK2010]Peaks加强版

题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(强制在线): #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; const int M = 5*N; template<typename T> inline void read(T&x) {

dtoi1927 [ONTAK2010]Peaks加强版

题意: 给一个n个点的图,每个点有权值,每条边有权值.q次询问,每次询问从a出发不经过边权大于x的边能够到达的所有点中,点权第k大的值. n<=100000,q<=500000 题解:      点权第k大的值,容易想到可持久化线段树,问题就在于如何把要查询的点转化为一段连续的区间. 考虑建立Kruskal重构树.这种树有一个性质,经过两个点的路径的边权最大值就是在重构树上的lca的点权. 因此可以倍增a的父亲到达最后一个点权小于等于x的节点,然后所有能到达的点就是其子树. 那么就在dfs序上

bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版

传送门:bzoj  bzoj wdnmd为什么加强版不是权限题原题却是啊 3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达