zoukankan      html  css  js  c++  java
  • bzoj2733: [HNOI2012]永无乡 线段树合并

    永无乡包含 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

    题解:建立权值线段树,然后线段树合并即可,复杂度O(nlogn),线段树合并需要动态开点

    /**************************************************************
        Problem: 2733
        User: walfy
        Language: C++
        Result: Accepted
        Time:2552 ms
        Memory:25900 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define ld long double
    #define C 0.5772156649
    //#define ls l,m,rt<<1
    //#define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
     
    using namespace std;
     
    const double eps=1e-6;
    const int N=100000+10,maxn=2000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    int tot,fa[N],id[N],root[N],ls[maxn],rs[maxn],val[maxn];
    inline int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}
    inline void pushup(int rt){val[rt]=val[ls[rt]]+val[rs[rt]];}
    void update(int &o,int pos,int l,int r)
    {
        o=++tot;
        if(l==r){val[o]=1;return ;}
        int m=(l+r)>>1;
        if(pos<=m)update(ls[o],pos,l,m);
        else update(rs[o],pos,m+1,r);
        pushup(o);
    }
    int query(int o,int k,int l,int r)
    {
        if(l==r)return id[l];
        int m=(l+r)>>1;
        if(k<=val[ls[o]])return query(ls[o],k,l,m);
        else return query(rs[o],k-val[ls[o]],m+1,r);
    }
    int Merge(int x,int y)
    {
        if(!x||!y)return x+y;
        ls[x]=Merge(ls[x],ls[y]);
        rs[x]=Merge(rs[x],rs[y]);
        pushup(x);
        return x;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int x;scanf("%d",&x);
            update(root[i],x,1,n);
            fa[i]=i;id[x]=i;
        }
        for(int i=1;i<=m;i++)
        {
            int a,b;scanf("%d%d",&a,&b);
            a=Find(a),b=Find(b);fa[b]=a;
            root[a]=Merge(root[a],root[b]);
        }
        int q;scanf("%d",&q);
        while(q--)
        {
            char op[10];int x,y;
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='B')
            {
                x=Find(x),y=Find(y);
                if(x!=y)
                {
                    fa[y]=x;
                    root[x]=Merge(root[x],root[y]);
                }
            }
            else
            {
                x=Find(x);
                if(val[root[x]]<y)puts("-1");
                else printf("%d
    ",query(root[x],y,1,n));
            }
        }
        return 0;
    }
    /********************
     
    ********************/
    
  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9141419.html
Copyright © 2011-2022 走看看