zoukankan      html  css  js  c++  java
  • [HNOI2012]永无乡

    题目描述

    永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。

    现在有两种操作:

    B x y 表示在岛 x 与岛 y 之间修建一座新桥。

    Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。

    输入输出格式

    输入格式:

    输入文件第一行是用空格隔开的两个正整数 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

    输出格式:

    对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。

    输入输出样例

    输入样例#1:
    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
    输出样例#1:
    -1
    2
    5
    1
    2
    题解:
    splay+并查集
    并查集判断两点是否联通,每个节点对应一个平衡树
    splay用启发式合并,通过线段树思想和调整顺序可以做到不用旋转

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int MAXN=500010,MAXM=2000005;
      7 int tot2,tot1,s[MAXN],pre[MAXM],ch[MAXM][2],key[MAXM];
      8 int size[MAXM],root[MAXN],n,m,set[MAXN],a[MAXN],sz,id[MAXN];
      9 void NewNode(int &x,int fa,int k)
     10 {
     11     if (tot2) x=s[tot2--];
     12     else x=++tot1;
     13     key[x]=k;
     14     size[x]=1;
     15     pre[x]=fa;
     16     ch[x][0]=ch[x][1]=0;
     17 }
     18 int find(int x)
     19 {
     20     if (set[x]!=x) set[x]=find(set[x]);
     21     return set[x];
     22 }
     23 void pushup(int x)
     24 {
     25     int lson=ch[x][0],rson=ch[x][1];
     26     size[x]=size[lson]+size[rson];
     27 }
     28 void insert(int &x,int l,int r,int d)
     29 {
     30     x=++sz;
     31     if (l==r) 
     32     {
     33      size[x]=1;
     34      return;
     35 }
     36     int mid=(l+r)>>1;
     37      if(d<=mid) insert(ch[x][0],l,mid,d); 
     38      else insert(ch[x][1],mid+1,r,d);
     39      pushup(x);
     40 }
     41 int merge(int x,int y)
     42 {
     43     if (!x) return y;
     44     if (!y) return x;
     45     ch[x][0]=merge(ch[x][0],ch[y][0]);
     46     ch[x][1]=merge(ch[x][1],ch[y][1]);
     47     pushup(x);
     48     return x;
     49 }
     50 int query(int x,int l,int r,int k)
     51 {
     52      if(l==r) return l;
     53      int mid=(l+r)>>1;
     54     if(size[ch[x][0]]>=k) return query(ch[x][0],l,mid,k);
     55     else return query(ch[x][1],mid+1,r,k-size[ch[x][0]]);
     56 }
     57 void erase(int r)
     58 {
     59     if (!r) return ;
     60     s[++tot2]=r;
     61     erase(ch[r][0]);
     62     erase(ch[r][1]);
     63 }
     64 void bridge_union(int x,int y)
     65 {
     66     int l=find(x),r=find(y);
     67     if (l!=r)
     68     {
     69         if (size[root[l]]<size[root[r]]) swap(l,r);
     70          set[r]=l;size[root[l]]+=size[root[r]];
     71          merge(root[l],root[r]);
     72          erase(root[r]);
     73     }
     74 }
     75 char get_op()
     76 {
     77     char ch=getchar();
     78     while (ch!='B'&&ch!='Q') ch=getchar();
     79     return ch;
     80 }
     81 int main()
     82 {int i,j,x,y,q,opt;
     83     cin>>n>>m;
     84       for (i=1;i<=n;i++)
     85       {
     86           scanf("%d",&a[i]);
     87           id[a[i]]=i;
     88            set[i]=i;
     89       }
     90       for (i=1;i<=n;i++)
     91        insert(root[i],1,n,a[i]);
     92        for (i=1;i<=m;i++)
     93        {
     94            scanf("%d%d",&x,&y);
     95            bridge_union(x,y);
     96        }
     97        cin>>q;
     98     for (i=1;i<=q;i++)
     99     {
    100         opt=get_op();
    101         scanf("%d%d",&x,&y);
    102         if (opt=='Q')
    103         {
    104             int l=find(x);
    105              if (size[root[l]]<y) printf("-1
    ");
    106              else 
    107             printf("%d
    ",id[query(root[l],1,n,y)]);
    108         }
    109         else 
    110         {
    111             bridge_union(x,y);
    112         }
    113     }
    114 }
  • 相关阅读:
    数据库主体拥有数据库角色,无法删除
    popupWin类QQ弹出窗口
    使用性能监视器找出硬件瓶颈
    关于反射中Assembly.CreateInstance()与Activator.CreateInstance()方法的区别
    大数据的通用分页总结!
    SQL 注入[转自:微软技术中心]
    【转】 使用Yahoo的公开API做天气预报
    JS对select动态添加options操作
    asp.net “从客户端检测到有潜在危险的Request.Form值” 处理办法
    SQL中索引的原理
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7210177.html
Copyright © 2011-2022 走看看