zoukankan      html  css  js  c++  java
  • bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)

    [HNOI2012]永无乡

    每个联通块的点集用动态开点线段树维护

    并查集维护图

    合并时把线段树也合并就好了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cctype>
     5 #define re register 
     6 #define gc getchar
     7 using namespace std;
     8 void chread(char &x){
     9     char c=gc();
    10     while(!isupper(c)) c=gc();
    11     x=c;
    12 }
    13 void read(int &x){
    14     char c=gc();x=0; bool f=1;
    15     while(!isdigit(c)) f=(f&&c!='-'),c=gc();
    16     while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=gc();
    17     x=f?x:-x;
    18 }
    19 void swap(int &a,int &b){a^=b;b^=a;a^=b;}
    20 #define N 100002
    21 #define M 600002
    22 struct edge{int u,v;bool del;}b[M];
    23 struct node{
    24     int sum,lc,rc;
    25 }c[M<<2];
    26 int n,m,t,u,val[N],fa[N],rt[N],ttp,id[N];
    27 double ans;
    28 
    29 void update(int &o,int l,int r,int v,int k){//插入
    30     if(!o) o=++u;
    31     if(l==r) {c[o].sum+=k; return;}
    32     int mid=l+((r-l)>>1);
    33     if(v<=mid) update(c[o].lc,l,mid,v,k);
    34     else update(c[o].rc,mid+1,r,v,k);
    35     c[o].sum=c[c[o].lc].sum+c[c[o].rc].sum;
    36 }
    37 void merge(int &o,int pr){//合并
    38     if(!o||!pr) {o+=pr;return;}
    39     c[o].sum+=c[pr].sum;
    40     merge(c[o].lc,c[pr].lc);
    41     merge(c[o].rc,c[pr].rc);
    42 }
    43 int query(int o,int l,int r,int k){//询问
    44     if(l==r) return l;
    45     int mid=l+((r-l)>>1);
    46     if(k<=c[c[o].lc].sum) return query(c[o].lc,l,mid,k);
    47     else return query(c[o].rc,mid+1,r,k-c[c[o].lc].sum);
    48 }
    49 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    50 void uni(int x,int y){//并查集合并
    51     int r1=find(x),r2=find(y);
    52     if(r1!=r2){
    53         merge(rt[r1],rt[r2]);
    54         fa[r2]=r1;
    55     }
    56 }
    57 int ask(int x,int k){
    58     int ffa=find(x);
    59     return k>c[rt[ffa]].sum ?-1:id[query(rt[ffa],1,n,k)];
    60 }
    61 int main(){
    62     char opt; int q1,q2;
    63     read(n); read(m);
    64     for(re int i=1;i<=n;++i){
    65         read(val[i]),id[val[i]]=i,fa[i]=i;
    66         update(rt[i],1,n,val[i],1);
    67     }
    68     for(re int i=1;i<=m;++i) read(q1),read(q2),uni(q1,q2);
    69     read(t);
    70     for(re int i=1;i<=t;++i){
    71         chread(opt); read(q1); read(q2); 
    72         switch(opt){
    73             case 'B':{uni(q1,q2); break;}
    74             case 'Q':{printf("%d
    ",ask(q1,q2));  break;}
    75         }
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    线索二叉树的构建和遍历------小甲鱼数据结构和算法
    小甲鱼数据结构和算法-----二叉树的构建和前序遍历
    python爬虫爬取煎蛋网妹子图片
    C语言实现汉诺塔问题
    C语言实现中缀表达式转后缀表达式
    深度优先算法--判断迷宫的一个起点能否到达一个终点
    python 爬取36K新闻
    栈的操作实现逆波兰表达式的计算
    python 实现汉诺塔问题
    【POJ 3258】River Hopscotch
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9845996.html
Copyright © 2011-2022 走看看