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
  • 相关阅读:
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Maximum Depth of Binary Tree
    Sharepoint 2013 创建TimeJob 自动发送邮件
    IE8 不能够在Sharepoint平台上在线打开Office文档解决方案
    TFS安装与管理
    局域网通过IP查看对方计算机名,通过计算机名查看对方IP以及查看在线所有电脑IP
    JS 隐藏Sharepoint中List Item View页面的某一个字段
    SharePoint Calculated Column Formulas & Functions
    JS 两个一组数组转二维数组
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9852786.html
Copyright © 2011-2022 走看看