BZOJ3545: [ONTAK2010]Peaks

题解:离线排序处理  并查集维护边 对于不同集合的启发式合并平衡树 查询第K大即可

/**************************************************************
    Problem: 3545
    User: c20161007
    Language: C++
    Result: Accepted
    Time:9736 ms
    Memory:19868 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define ll long long
const int NM=1e5+10;
const int nm=5e5+10;
using namespace std;
int ch[NM][2],size[NM],key[NM],pre[NM];
int f[NM];
struct FastIO
{
    static const int S=200;
    int wpos;
    char wbuf[S];
    FastIO():wpos(0){}
    inline int xchar()
    {
        static char buf[S];
        static int len=0,pos=0;
        if(pos==len) pos=0,len=fread(buf,1,S,stdin);
        if(pos==len) exit(0);
        return buf[pos++];
    }
    inline int read()
    {
        int s=1,c=xchar(),x=0;
        while(c<=32) c=xchar();
        if(c=='-') s=-1,c=xchar();
        for(;'0'<=c&&c<='9';c=xchar()) x=x*10+c-'0';
        return x*s;
    }
    ~FastIO()
    {
        if(wpos) fwrite(wbuf,1,wpos,stdout),wpos=0;
    }
}io;
typedef struct Edge{
    int u,v;int vul;
    friend bool operator<(Edge aa,Edge bb){
    return aa.vul<bb.vul;
    }
}Edge;
Edge ed[nm];
typedef struct node{
    int v,x,k;int id;
    friend bool operator<(node aa,node bb){
    return aa.x<bb.x;
    }
}node;
node que[nm];
void newnode(int x){
    pre[x]=0;ch[x][0]=ch[x][1]=0;size[x]=1;
}
int n,m,q;
int find1(int x){
    if(f[x]==x)return x;
    else return f[x]=find1(f[x]);
}
void up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}
void rotate(int x,int kind){
    int y=pre[x];
    ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
    pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
    up(y);
}
void splay(int x){
    while(pre[x]!=0){
    if(pre[pre[x]]==0)rotate(x,ch[pre[x]][0]==x);
    else{
        int y=pre[x];int kind=ch[pre[y]][0]==y;
        if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
        else rotate(y,kind),rotate(x,kind);
    }
    }
    up(x);
}
void insert(int &x,int pos,int fa){
    if(!x){x=pos;pre[pos]=fa;return ;}
    if(key[x]>key[pos])insert(ch[x][1],pos,x);
    else insert(ch[x][0],pos,x);
    up(x);
}
int S[NM];
void dfs(int x){
    if(!x)return ;
    S[++S[0]]=x;
    dfs(ch[x][0]);
    dfs(ch[x][1]);
}
void merge(int u,int v){
    splay(u);splay(v);
    if(size[u]>size[v])swap(u,v);
    S[0]=0;dfs(u);int t=v;
    for(int i=1;i<=S[0];i++)newnode(S[i]),insert(t,S[i],0),splay(S[i]),t=S[i];
    //splay(S[S[0]]);
}
int find2(int x,int sz){
    if(sz==size[ch[x][0]]+1)return x;
    else if(sz<=size[ch[x][0]])return find2(ch[x][0],sz);
    else return find2(ch[x][1],sz-size[ch[x][0]]-1);
}
int querty(int v,int k){
    splay(v);
    if(size[v]<k)return -1;
    return key[find2(v,k)];
}
int ans[nm];
int main(){
    n=io.read();m=io.read();q=io.read();
    for(int i=1;i<=n;i++)key[i]=io.read(),newnode(i),f[i]=i;
    for(int i=1;i<=m;i++)ed[i].u=io.read(),ed[i].v=io.read(),ed[i].vul=io.read();
    for(int i=1;i<=q;i++)que[i].v=io.read(),que[i].x=io.read(),que[i].k=io.read(),que[i].id=i;
    sort(ed+1,ed+m+1);sort(que+1,que+1+q);
    int l=1;
    for(int i=1;i<=q;i++){
    while(l<=m&&que[i].x>=ed[l].vul){
        int t1=find1(ed[l].u);int t2=find1(ed[l].v);
        if(t1!=t2){
        merge(t1,t2);f[t1]=t2;
        }
        l++;
    }
    ans[que[i].id]=querty(que[i].v,que[i].k);
    }
    for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
    return 0;
}

 

3545: [ONTAK2010]Peaks

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3083  Solved: 837
[Submit][Status][Discuss]

Description

在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,表示一组询问。

Output

对于每组询问,输出一个整数表示答案。

Sample Input

10 11 4
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2

Sample Output

6
1
-1
8


HINT

【数据范围】

N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

posted @ 2018-08-05 15:57  wang9897  阅读(150)  评论(0编辑  收藏  举报