bzoj3545: [ONTAK2010]Peaks 主席树合并

排序以后,做并茶几+主席树合并维护,Orzstdcall,没想到权值线段树的合并竟然是O(nlogn)的...虽然他给我证明了一波,但是还是不是十分理解...听说是Cydiater给他讲的,Orz

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
struct one
{int x,id,y,v,f;};
one e[2200010];
int f1,f2,n,m,q,cnt=0,root[501000],hash[501000],fa[501000],a[501000],sum[6000000],l[6000000],r[6000000],ans[500100];
bool cmp(one aa,one bb){if(aa.v==bb.v)return aa.f<bb.f;else return aa.v<bb.v;}
void add(int &pre,int L,int R,int x)
{
    if(!pre)pre=++cnt;sum[pre]=1;
    if(L>=R)return;
    int mid=(L+R)>>1;
    if(x<=mid){add(l[pre],L,mid,x);}
    else {add(r[pre],mid+1,R,x);}
}
int getfather(int pp)
{
    if(pp==fa[pp])return pp;
    else return fa[pp]=getfather(fa[pp]);
}
int merge(int aa,int bb)
{
    if(!aa)return bb;
    if(!bb)return aa;
    if((!l[aa])&&(!r[aa]))
    {
        sum[aa]+=sum[bb];
        return aa;
    }
    l[aa]=merge(l[aa],l[bb]);
    r[aa]=merge(r[aa],r[bb]);
    sum[aa]=sum[l[aa]]+sum[r[aa]];
    return aa;
}
int query(int pre,int L,int R,int x)
{
    if(L>=R)return L;
    int mid=(L+R)>>1;
    if(x<=sum[l[pre]])return query(l[pre],L,mid,x);
    else return query(r[pre],mid+1,R,x-sum[l[pre]]);
}
int main()
{
    //freopen("xf.in","r",stdin);
    //freopen("xf.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)a[i]=read(),hash[i]=a[i];
    sort(hash+1,hash+n+1);
    for(int i=1;i<=m;i++)
    {
        e[i].x=read();
        e[i].y=read();
        e[i].v=read();
        e[i].f=0;
    }
    for(int i=m+1;i<=m+q;i++)
    {
        e[i].x=read();
        e[i].v=read();
        e[i].y=read();
        e[i].f=1;
        e[i].id=i-m;
    }
    sort(e+1,e+q+m+1,cmp);
    for(int i=1;i<=n;i++)
    {
        int x=lower_bound(hash+1,hash+n+1,a[i])-hash;
        add(root[i],1,n,x);
    }
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m+q;i++)
    {
        if(!e[i].f)
        {
            f1=getfather(e[i].x);
            f2=getfather(e[i].y);
            if(f1==f2)continue;
            fa[f1]=f2;
            root[f2]=merge(root[f1],root[f2]);
        }
        else
        {
            f1=getfather(e[i].x);
            if(sum[root[f1]]<e[i].y)ans[e[i].id]=-1;
            else ans[e[i].id]=hash[query(root[f1],1,n,sum[root[f1]]-e[i].y+1)];
        }
    }
    for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
    return 0;
}

  

原文地址:https://www.cnblogs.com/mybing/p/8613383.html

时间: 2024-10-09 04:51:44

bzoj3545: [ONTAK2010]Peaks 主席树合并的相关文章

【bzoj3545】[ONTAK2010]Peaks 线段树合并

[bzoj3545][ONTAK2010]Peaks 2014年8月26日3,1512 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有一条困难

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MB Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q.第二行N个数,第i个数为h_i接下来M行,每行

[BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)

传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n #include <cstdio> #include <iostream> #include <algorithm> #define N 500001 int n, m, q, cnt, tot, size; int sum[N * 10], ls[N * 10], rs[N

【线段树合并】bzoj3545: [ONTAK2010]Peaks

1A还行 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,表示一组询问. Outpu

bzoj3545 Peaks 线段树合并

离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m,q,tot,cnt,num,h[100001],a[100001],ans[500001],fa[100001],root[100001]; struct edge{ int u,v,cost; bool ope

bzoj3545 [ONTAK2010]Peaks

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 572  Solved: 164[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

bzoj3545 [ONTAK2010]Peaks、bzoj3551 [ONTAK2010]Peaks加强版

题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(强制在线): #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; const int M = 5*N; template<typename T> inline void read(T&x) {

【Tyvj2133 BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)

题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路:此题明显地体现了我对主席树理解不深 树上路径K大可以直接用树剖+二分答案+树做 但DFS序+主席树也可以 对于点U,它能影响DFS序上的区间(st[u],ed[u]) 所以维护方法就是类似序列K大一样 s[st[u]]++ s[ed[u]+1]-- 对于路径(x,y),信息为s[x]+s[y]-s[lca(x

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

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I