3545: [ONTAK2010]Peaks 启发式合并treap 离线处理

《多年的心头大恨终于解决了系列》
一个半月前写的splay挂了。。于是来写了一发treap,好慢。。
离线随便搞。
听说有强制在线版本?

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define N 100005
#define M 500005
using namespace std;
int n,m,Q,tmp;
int ls[N],rs[N],val[N],h[N],size[N],rnd[N],f[N],root[N];
struct node {int x,y,z,id,ans;} e[M],q[M];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool cmp(node a,node b)
{
    return a.z<b.z;
}
inline bool cmp0(node a,node b)
{
    return a.id<b.id;
}
int find(int i)
{
    return f[i]==i?i:f[i]=find(f[i]);
}
inline void pushup(int k)
{
    size[k]=size[ls[k]]+size[rs[k]]+1;
}
inline void lturn(int &k)
{
    int t=rs[k]; rs[k]=ls[t]; ls[t]=k; pushup(k); pushup(t); k=t;
}
inline void rturn(int &k)
{
    int t=ls[k]; ls[k]=rs[t]; rs[t]=k; pushup(k); pushup(t); k=t;
}
inline void insert(int &k,int v,int id)
{
    if (!k)
    {
        k=id;
        val[k]=v;
        rnd[k]=rand();
        size[k]=1;
        return;
    }
    size[k]++;
    if (v<=val[k])
    {
        insert(ls[k],v,id);
        if (rnd[ls[k]]<rnd[k]) rturn(k);
    }
    else
    {
        insert(rs[k],v,id);
        if (rnd[rs[k]]<rnd[k]) lturn(k);
    }
}
void add(int x,int &y)
{
    if (!x) return;
    add(ls[x],y);
    add(rs[x],y);
    ls[x]=rs[x]=0;
    insert(y,h[x],x);
}
inline void merge(int x,int y)
{
    if (size[root[x]]>size[root[y]]) swap(x,y);
    f[x]=y;
    add(root[x],root[y]);
}
void query(int k,int rank)
{
    if (size[ls[k]]+1==rank) tmp=val[k];
    else if (size[ls[k]]+1>rank) query(ls[k],rank);
    else query(rs[k],rank-size[ls[k]]-1);
}
int main()
{
    n=read(); m=read(); Q=read();
    for (int i=1;i<=n;i++) h[i]=read();
    for (int i=1;i<=m;i++) 
        e[i].x=read(),e[i].y=read(),e[i].z=read();
    for (int i=1;i<=Q;i++)
        q[i].x=read(),q[i].z=read(),q[i].y=read(),q[i].id=i;
    sort(e+1,e+m+1,cmp);
    sort(q+1,q+Q+1,cmp);
    for (int i=1;i<=n;i++) f[i]=i;
    for (int i=1;i<=n;i++) insert(root[i],h[i],i);
    int now=1;
    for (int i=1;i<=Q;i++)
    {
        while (e[now].z<=q[i].z&&now<=m)
        {
            int p=find(e[now].x),q=find(e[now].y);
            if (p!=q) merge(p,q);           
            now++;
        }
        int p=find(q[i].x);
        if (size[root[p]]<q[i].y) q[i].ans=-1;
        else
        {
            int rank=size[root[p]]-q[i].y+1;
            query(root[p],rank);
            q[i].ans=tmp;
        }
    }
    sort(q+1,q+Q+1,cmp0);
    for (int i=1;i<=Q;i++) printf("%d\n",q[i].ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值