zoukankan      html  css  js  c++  java
  • Bzoj 2733: [HNOI2012]永无乡(线段树+启发式合并)

    2733: [HNOI2012]永无乡
    Time Limit: 10 Sec Memory Limit: 128 MB
    Description
    永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。
    Input
    输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000
    对于 100%的数据 n≤100000,m≤n,q≤300000
    Output
    对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。
    Sample Input
    5 1
    4 3 2 5 1
    1 2
    7
    Q 3 2
    Q 2 1
    B 2 3
    B 1 5
    Q 2 1
    Q 2 4
    Q 2 3
    Sample Output
    -1
    2
    5
    1
    2

    /*
    线段树+启发式合并.
    对于每个叶节点建立一棵权值线段树.
    然后发现对于每个联通块的值域是一样的.
    然后就可以合并辣.
    貌似这题还可以搞splay+启发合并
    复杂度是O(nlogn2).
    期望重构次数是nlogn次,每一次重构需要更新一条链,复杂度是logn的,
    所以总复杂度是nlogn2的.
    如果用平衡树的话也是nlogn2的.
    某度贴吧中说用Finger Search可以降一个log.
    但是好像没找到这方面的资料orz.
    */
    #include<iostream>
    #include<cstdio>
    #define MAXN 100001
    using namespace std;
    int n,m,q,tot,root[MAXN],a[MAXN],father[MAXN],size[MAXN],s[MAXN];
    struct data{int lc,rc,size;}tree[MAXN*20];
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    int find(int x)
    {
        return x!=father[x]?father[x]=find(father[x]):x;
    }
    void add(int &k,int l,int r,int x)
    {
        if(!k) k=++tot;
        if(l==r){tree[k].size=1;return ;}
        int mid=(l+r)>>1;
        if(x<=mid) add(tree[k].lc,l,mid,x);
        else add(tree[k].rc,mid+1,r,x);
        tree[k].size=tree[tree[k].lc].size+tree[tree[k].rc].size;
        return ;
    }
    int query(int k,int l,int r,int x)
    {
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(tree[tree[k].lc].size>=x) return query(tree[k].lc,l,mid,x);
        else return query(tree[k].rc,mid+1,r,x-tree[tree[k].lc].size);
    }
    int slove(int x,int y)
    {
        if(!x) return y;
        if(!y) return x;
        tree[x].lc=slove(tree[x].lc,tree[y].lc);
        tree[x].rc=slove(tree[x].rc,tree[y].rc);
        tree[x].size=tree[tree[x].lc].size+tree[tree[x].rc].size;
        return x;
    }
    int main()
    {
        int x,y,k;char ch[3];
        n=read(),m=read();
        for(int i=1;i<=n;i++) a[i]=read(),father[i]=i,s[a[i]]=i;
        for(int i=1;i<=m;i++)
        {
            x=read(),y=read();
            int l1=find(x),l2=find(y);
            father[l1]=l2;
        }
        for(int i=1;i<=n;i++)
        {
            int l1=find(i);
            add(root[l1],1,n,a[i]);
        }
        q=read();
        while(q--)
        {
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                x=read(),k=read();
                int l1=find(x);
                if(tree[root[l1]].size<k) printf("-1
    ");
                else printf("%d
    ",s[query(root[l1],1,n,k)]);
            }
            else
            {
                x=read(),y=read();
                int l1=find(x),l2=find(y);
                if(l1!=l2) 
                {
                    father[l2]=l1;
                    root[l1]=slove(root[l1],root[l2]);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    hdu 5446 Unknown Treasure lucas和CRT
    Hdu 5444 Elven Postman dfs
    hdu 5443 The Water Problem 线段树
    hdu 5442 Favorite Donut 后缀数组
    hdu 5441 Travel 离线带权并查集
    hdu 5438 Ponds 拓扑排序
    hdu 5437 Alisha’s Party 优先队列
    HDU 5433 Xiao Ming climbing dp
    hdu 5432 Pyramid Split 二分
    Codeforces Round #319 (Div. 1) B. Invariance of Tree 构造
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068064.html
Copyright © 2011-2022 走看看