zoukankan      html  css  js  c++  java
  • ONTAK2010 Peaks加强版

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

    强制在线

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

    $n leq 10^5$

    $m,q leq 5 imes 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
    ",lastans);
           // lastans = 0;
        }
    }
    View Code
  • 相关阅读:
    Next Permutation
    Generate Parentheses
    Unique Binary Search Trees II
    LDP LSP建立
    LDP标签分发和管理
    维护LDP会话
    LDP会话状态机
    LDP会话建立过程
    LDP发现机制
    LDP术语
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9852786.html
Copyright © 2011-2022 走看看