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

    2733: [HNOI2012]永无乡

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1130  Solved: 583
    [Submit][Status]

    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

    HINT

     

    Source

    题解:

    因为支持的操作只有 新建一条边,查询某个连通块内的第k小的值

    所以我们考虑用平衡树启发式合并+并查集来完成

    刚开始每个节点为一棵平衡树,merge操作只需要找到代表元暴力把小的合并的到大的里面即可

    查询操作则直接在代表元的平衡树里面select即可

    代码:

      1 const maxn=100000+1000;
      2 var l,r,s,rnd,v,fa:array[0..maxn] of longint;
      3     i,n,m,x,y,xx,yy,rk:longint;
      4     ch:char;
      5     procedure swap(var x,y:longint);
      6      var t:longint;
      7        begin
      8         t:=x;x:=y;y:=t;
      9        end;
     10 procedure pushup(k:longint);
     11  begin
     12    s[k]:=s[l[k]]+s[r[k]]+1;
     13  end;
     14 procedure rturn(var k:longint);
     15  var t:longint;
     16  begin
     17    t:=l[k];l[k]:=r[t];r[t]:=k;s[t]:=s[k];pushup(k);k:=t;
     18  end;
     19 procedure lturn(var k:longint);
     20  var t:longint;
     21  begin
     22    t:=r[k];r[k]:=l[t];l[t]:=k;s[t]:=s[k];pushup(k);k:=t;
     23  end;
     24 procedure ins(var k,x:longint);
     25  begin
     26   if k=0 then
     27    begin
     28     k:=x;s[k]:=1;l[k]:=0;r[k]:=0;
     29     rnd[k]:=random(maxlongint);exit;
     30    end;
     31   inc(s[k]);
     32   if v[x]<v[k] then begin ins(l[k],x);if rnd[l[k]]<rnd[k] then rturn(k);end
     33   else begin ins(r[k],x);if rnd[r[k]]<rnd[k] then lturn(k);end;
     34  end;
     35 procedure print(x:longint);
     36  begin
     37  if x=0 then exit;
     38  print(l[x]);
     39  write(x,' ',v[x],'!');
     40  print(r[x]);
     41  end;
     42 function select(k,rk:longint):longint;
     43  begin
     44  if s[l[k]]+1=rk then exit(k)
     45  else if s[l[k]]>=rk then exit(select(l[k],rk))
     46  else exit(select(r[k],rk-1-s[l[k]]));
     47  end;
     48 function find(x:longint):longint;
     49  begin
     50   if fa[x]<>x then fa[x]:=find(fa[x]);
     51   exit(fa[x]);
     52  end;
     53 procedure merge(x,y:longint);
     54  begin
     55   if x=0 then exit;
     56   merge(l[x],y);merge(r[x],y);ins(y,x);
     57  end;
     58 procedure solvemerge;
     59  begin
     60   readln(x,y);
     61   xx:=find(x);yy:=find(y);
     62   if s[xx]>s[yy] then swap(xx,yy);
     63   fa[xx]:=yy;
     64   merge(xx,yy);
     65  end;
     66 procedure solveask;
     67  begin
     68   readln(x,rk);
     69   xx:=find(x);
     70   if rk>s[xx] then writeln('-1') else writeln(select(xx,rk));
     71  end;
     72 procedure init;
     73  begin
     74   readln(n,m);
     75   for i:=1 to n do
     76    begin
     77      read(v[i]);
     78      fa[i]:=i;s[i]:=1;l[i]:=0;r[i]:=0;
     79    end;
     80   for i:=1 to m do solvemerge;
     81  end;
     82 procedure main;
     83  begin
     84   readln(m);
     85   for i:=1 to m do
     86    begin
     87      read(ch);
     88      case ch of
     89      'B':solvemerge;
     90      'Q':solveask;
     91      end;
     92    end;
     93  end;
     94 begin
     95   assign(input,'input.txt');assign(output,'output.txt');
     96   reset(input);rewrite(output);
     97   init;
     98   main;
     99   close(input);close(output);
    100 end.    
    View Code
  • 相关阅读:
    JavaScript.how-to-debug-javascript
    iOS.mach_absolute_time
    Startup.国外新锐公司及其技术Blog
    Android.FamousBlogs
    iOS.PrototypeTools
    Android.API.Context.getFilesDir()
    Android.Tools.Ant
    Tools.OnlineAPIs
    Java.Class
    Android.StructureOfAndroidSourceCodeRootTree
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3915213.html
Copyright © 2011-2022 走看看