• 2733: [HNOI2012]永无乡 线段树合并


    题目:

      https://www.lydsy.com/JudgeOnline/problem.php?id=2733

    题解:

      建n棵动态开点的权值线段树,然后边用并查集维护连通性,边合并线段树维护第k重要。

      其实实现还是很简单的。。

    代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn=300010;
     6 int fa[maxn],root[maxn],n,m,g[maxn],f[maxn],id;
     7 char ch[3];
     8 
     9 struct Tr{
    10     int lt,rt,num;
    11     int ch[2];
    12 }tree[maxn<<3];
    13 
    14 void update(int now){
    15     tree[now].num=tree[tree[now].ch[0]].num+tree[tree[now].ch[1]].num;
    16 }
    17 
    18 int merge(int now,int last){
    19     if(!now) return last;
    20     else if(!last) return now;
    21     if(tree[now].num<tree[last].num) swap(now,last);
    22     tree[now].ch[0]=merge(tree[now].ch[0],tree[last].ch[0]);
    23     tree[now].ch[1]=merge(tree[now].ch[1],tree[last].ch[1]);
    24     update(now);return now;
    25 }
    26 
    27 int ffa(int x){
    28     return fa[x]==x?x:fa[x]=ffa(fa[x]);
    29 }
    30 
    31 void connect(int u,int v){
    32     int fu=ffa(u),fv=ffa(v);
    33     if(fu!=fv) root[fu]=merge(root[fu],root[fv]),fa[fv]=fu;
    34 }
    35 
    36 void build(int &now,int w,int lt,int rt){
    37     now=++id;
    38     tree[now].lt=lt,tree[now].rt=rt;
    39     if(lt==rt){ tree[now].num=1;return ;}
    40     int mid=lt+rt>>1;
    41     if(w<=mid) build(tree[now].ch[0],w,lt,mid);
    42     else build(tree[now].ch[1],w,mid+1,rt);
    43     update(now);
    44 }
    45 
    46 int ask(int now,int k){
    47     if(tree[now].num<k) return -1;if(tree[now].lt==tree[now].rt) return tree[now].lt;
    48     if(tree[tree[now].ch[0]].num>=k) return ask(tree[now].ch[0],k);
    49     else return ask(tree[now].ch[1],k-tree[tree[now].ch[0]].num);
    50 }
    51 
    52 int main(){
    53     //freopen("1.in","r",stdin);
    54     scanf("%d%d",&n,&m);
    55     for(int i=1;i<=n;i++) fa[i]=i;
    56     for(int i=1;i<=n;i++){
    57         scanf("%d",&g[i]);f[g[i]]=i;
    58         build(root[i],g[i],1,n);    
    59     } int u,v,x,y,tt;
    60     for(int i=1;i<=m;i++) scanf("%d%d",&u,&v),connect(u,v);
    61     scanf("%d",&m);
    62     for(int i=1;i<=m;i++){
    63         scanf("%s%d%d",ch,&x,&y);
    64         if(ch[0]=='Q') 
    65             tt=ask(root[ffa(x)],y),printf("%d
    ",tt==-1?-1:f[tt]);
    66         else connect(x,y);
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    angry_birds_again_and_again(2014年山东省第五届ACM大学生程序设计竞赛A题)
    数学入门题目
    POJ1236:Network of Schools(tarjan+缩点)?
    POJ2186:Popular Cows(tarjan+缩点)
    HDU2426:Interesting Housing Problem(还没过,貌似入门题)
    POJ1175:Starry Night(bfs)
    POJ2506:Tiling(递推+大数斐波那契)
    POJ2135:Farm Tour
    POJ2195:Going Home(费用流入门)
    POJ1273:Drainage Ditches(最大流入门 EK,dinic算法)
  • 原文地址:https://www.cnblogs.com/tang666/p/8848156.html
Copyright © 2020-2023  润新知