题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3551

题意:给出一个图,n个点,m条边。边有权值点也有权值。若干询问,(v,x,k),问从v点开始经过边权不大于x的所有边到达的所有点中权值第K大的权值。强制在线。

思路:首先不在最小生成树上的边没用。将边权按照升序排序,并查集每次合并两个集合(x,y)时,新增一个点u,u的权值为这条边的权值,连有向边<u,x><u,y>。那么最后的这棵树是一个二叉树,从下到上权值增大。那么每次倍增求出最上的点r,那么以r为根的子树包含的所有点就是通过不大于x的所有边到达的点。因此dfs序+主席树(按照键值大小),那么每次查询r管辖的区间即可。

const int N=200005;

int n,h[N],b[N];
pair<int,pair<int,int> > E[N*3];
int m,Q;

int S[N];

int M;

int get(int x)
{
    if(S[x]!=x) S[x]=get(S[x]);
    return S[x];
}

vector<int> g[N];

int mp[N<<1],id;
int visit[N];
int st[N],ed[N];

int f[N][20],Max[N][20];

int eLen[N];

void DFS(int u)
{
    visit[u]=1;
    mp[++id]=u;

    int i;
    for(i=0;i<SZ(g[u]);i++)
    {
        int v=g[u][i];
        f[v][0]=u;
        Max[v][0]=eLen[u];
        DFS(v);
    }

    if(u>n) mp[++id]=u;
}

struct node
{
    int lson,rson,sum;
};

node a[N*25];
int e;
int root[N<<1];

int build(int L,int R)
{
    int t=++e;
    a[t].lson=a[t].rson=-1;
    a[t].sum=0;

    if(L==R) return t;

    int M=(L+R)>>1;
    a[t].lson=build(L,M);
    a[t].rson=build(M+1,R);
    return t;
}

void insert(int &t1,int t,int L,int R,int h)
{
    t1=++e;
    a[t1]=a[t];
    a[t1].sum++;

    if(L==R) return;

    int M=(L+R)>>1;
    if(h<=M) insert(a[t1].lson,a[t].lson,L,M,h);
    else insert(a[t1].rson,a[t].rson,M+1,R,h);
}

int get(int u,int x)
{
    int i;
    for(i=19;i>=0;i--) if(f[u][i]&&Max[u][i]<=x)
    {
        u=f[u][i];
    }
    return u;
}

int query(int rt1,int rt2,int L,int R,int k)
{
    if(L==R) return L;
    int tmp=a[a[rt2].lson].sum-a[a[rt1].lson].sum;
    int M=(L+R)>>1;
    if(tmp>=k) return query(a[rt1].lson,a[rt2].lson,L,M,k);
    else return query(a[rt1].rson,a[rt2].rson,M+1,R,k-tmp);
}

int main()
{

    n=getInt();
    m=getInt();
    Q=getInt();
    int i;
    for(i=1;i<=n;i++) h[i]=b[i]=getInt();
    sort(b+1,b+n+1);
    M=unique(b+1,b+n+1)-(b+1);
    for(i=1;i<=n;i++) h[i]=lower_bound(b+1,b+M+1,h[i])-b;

    for(i=1;i<=n+n;i++) S[i]=i;
    for(i=1;i<=m;i++)
    {
        int u=getInt();
        int v=getInt();
        int w=getInt();
        E[i]=MP(w,MP(u,v));
    }
    sort(E+1,E+m+1);
    int cur=n;
    for(i=1;i<=m;i++)
    {
        int u=E[i].second.first;
        int v=E[i].second.second;
        int w=E[i].first;
        if(get(u)==get(v)) continue;

        u=get(u);
        v=get(v);
        cur++;
        S[get(u)]=S[get(v)]=cur;
        g[cur].pb(u);
        g[cur].pb(v);
        eLen[cur]=w;
    }

    for(i=1;i<=n;i++) if(!visit[i]) DFS(get(i));

    int j;
    for(i=1;(1<<i)<=cur;i++) for(j=1;j<=cur;j++)
    {
        f[j][i]=f[f[j][i-1]][i-1];
        Max[j][i]=max(Max[j][i-1],Max[f[j][i-1]][i-1]);
    }

    clr(root,-1);
    root[0]=build(1,M);

    for(i=1;i<=id;i++)
    {

        int u=mp[i];

        if(u<=n) insert(root[i],root[i-1],1,M,h[u]);
        else
        {
            root[i]=root[i-1];
            if(st[u]==0) st[u]=i;
            else ed[u]=i;
        }
    }

    int ans=0;
    while(Q--)
    {
        int v=getInt();
        int x=getInt();
        int k=getInt();

        if(-1!=ans) v^=ans,x^=ans,k^=ans;

        int t=get(v,x);
        int L=st[t],R=ed[t];
        int cnt=a[root[R]].sum-a[root[L]].sum;
        if(cnt<k) ans=-1;
        else ans=b[query(root[L],root[R],1,M,cnt+1-k)];
        printf("%d\n",ans);
    }

}

BZOJ 3551 Peaks加强版的更多相关文章

  1. Peaks BZOJ 3545 / Peaks加强版 BZOJ 3551

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

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

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

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

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

  4. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  5. 3551: [ONTAK2010]Peaks加强版

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

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

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

  7. 【BZOJ3551】Peaks加强版(Kruskal重构树,主席树)

    [BZOJ3551]Peaks加强版(Kruskal重构树,主席树) 题面 BZOJ Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相 ...

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

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

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

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

随机推荐

  1. Android SDK Manager更新报错

    错误log: Fetching https://dl-ssl.google.com/android/repository/addons_list-.xml Fetched Add-ons List s ...

  2. 锋利的JQuery(二)

    释义: DOM:Document Object Model 文档对象模型 DOM操作细分:DOM Core .HTML-DOM.CSS-DOM text():对HTML文档和XML文档都有效

  3. C#操作CSV存取类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  4. java.lang.Runtime类总结 【转】

    转自:http://blog.chinaunix.net/uid-128922-id-289994.html  Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类 ...

  5. linux的mtd架构分析【转】

    转自:http://blog.csdn.net/column/details/xgbing-linux-mtd.html linux mtd 嵌入式系统的存储有很多不可靠之处.随着使用容量的增大,现在 ...

  6. Linux内存管理原理【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3695517.html 本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址 ...

  7. db2常用函数(1)

    VALUE函数 语法:VALUE(EXPRESSION1,EXPRESSION2) VALUE函数是用返回一个非空的值,当其第一个参数非空,直接返回该参数的值,如果第一个参数为空,则返回第一个参数的值 ...

  8. iOS Button按钮 热区的放大

      Apple的iOS人机交互设计指南中指出,按钮点击热区应不小于44x44pt,否则这个按钮就会让用户觉得“很难用”,因为明明点击上去了,却没有任何响应. 但我们有时做自定义Button的时候,设计 ...

  9. java正则表达式四种常用的处理方式是怎么样呢《匹配、分割、代替、获取》

    java 正则表达式高级篇,介绍四种常用的处理方式:匹配.分割.替代.获取,具体内容如下package test; import java.util.regex.Matcher; import jav ...

  10. APP运营推广那点事【干货】

    你的手机里面有多少应用?什么样的手机应用吸引你?下载之后经常用还是让他shi在那里?又或者刚点进去就卸载? 一款成功的应用,开发APP只是第一步,比前者更重要的是“养”APP,APP就像是一个需要不断 ...