BZOJ3545 Peaks

题目

在$Bytemountains$有N座山峰,每座山峰有他的高度$h_i$。有些山峰之间有双向道路相连,共$M$条路径,每条路径有一个困难值,这个值越大表示越难走,现在有$Q$组询问,每组询问询问从点v开始只经过困难值小于等于$x$的路径所能到达的山峰中第$k$高的山峰,如果无解输出$-1$。

思路

首先打开题解$kruskal重构树$+$主席树$?告辞。但是发现不是在线询问,好像可以苟一苟,思考下离线做法。对于每个询问,按照困难值排序,并顺次放入小于困难值的边貌似就可以解决只经过困难值小于等于$x$的路径所能到达的山峰这一条件了,那么第k大用权值线段树合并或者平衡树合并就可以搞定了。但是常 数 过 大以至于我(人丑常数大)只能开O2过,太屑了。

代码

#include<bits/stdc++.h>
#define Maxn 200005
#define Maxm 1000005
using namespace std;
int id=0,n,m,q,rt[Maxn],fa[Maxn],h[Maxn],p=1,size[Maxn];
struct edge{int u,v,w;}x[Maxm];
struct question{int v,x,k,id,ans;}Q[Maxm];
struct seg{int ls,rs,sum;}tree[Maxn*20];
bool cmp1(edge a,edge b){return a.w<b.w;}
bool cmp2(question a,question b){return a.x<b.x;}
bool cmp3(question a,question b){return a.id<b.id;}
inline void read(int &x)
{
    int f=1;x=0;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    x*=f;
}
inline void insert(int &root,int l,int r,int x)
{
    if (!root) root=++id;
    if (l==r) {tree[root].sum++;return;}
    int mid=l+r>>1;
    if (x<=mid) insert(tree[root].ls,l,mid,x);
    else insert(tree[root].rs,mid+1,r,x);
    tree[root].sum=tree[tree[root].ls].sum+tree[tree[root].rs].sum;
} 
inline int getfa(int x){if (fa[x]==x) return x;else return fa[x]=getfa(fa[x]);}
inline int merge(int x,int y,int l,int r)
{
    if (!x||!y) return x|y;
    if (l==r) {tree[x].sum+=tree[y].sum;return x;}
    int mid=l+r>>1;
    tree[x].ls=merge(tree[x].ls,tree[y].ls,l,mid);
    tree[x].rs=merge(tree[x].rs,tree[y].rs,mid+1,r);
    tree[x].sum=tree[tree[x].ls].sum+tree[tree[x].rs].sum;
    return x;
}
inline int query(int root,int l,int r,int k)
{
    if (l==r) return l;
    int mid=l+r>>1;
    if (tree[tree[root].ls].sum>=k) return query(tree[root].ls,l,mid,k);
    else return query(tree[root].rs,mid+1,r,k-tree[tree[root].ls].sum);
}
int main()
{
    read(n),read(m),read(q);
    for (int i=1;i<=n;i++) read(h[i]),insert(rt[i],1,1e9,h[i]),fa[i]=i,size[i]=1;
    for (int i=1;i<=m;i++) read(x[i].u),read(x[i].v),read(x[i].w);
    sort(x+1,x+m+1,cmp1);
    for (int i=1;i<=q;i++) read(Q[i].v),read(Q[i].x),read(Q[i].k),Q[i].id=i;
    sort(Q+1,Q+q+1,cmp2);
    for (int i=1;i<=q;i++)
    {
        while (x[p].w<=Q[i].x&&p<=m)
        {
            int fx=getfa(x[p].u),fy=getfa(x[p].v);
            if (fx==fy) {p++;continue;}
            fa[fy]=fx;
            size[fx]+=size[fy];
            rt[fx]=merge(rt[fx],rt[fy],1,1e9);
            p++;
        }
        int fz=getfa(Q[i].v);
        if (size[fz]<Q[i].k) Q[i].ans=-1;else Q[i].ans=query(rt[fz],1,1e9,size[fz]-Q[i].k+1);
    }
    sort(Q+1,Q+q+1,cmp3);
    for (int i=1;i<=q;i++) cout<<Q[i].ans<<endl;
    return 0;
}
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇