zoukankan      html  css  js  c++  java
  • 森林 BZOJ 3123

    题解:

    第k大直接用主席树解决

    合并利用启发式合并,将较小的连接到较大的树上

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 using namespace std;
      8 const int inf = 2e9;
      9 const int logn = 17;
     10 const int maxn = 8e4 + 233;
     11 const int maxm = 2e5;
     12 int t, n, m, q;
     13 int sum[maxn * 500], lc[maxn * 500], rc[maxn * 500];
     14 int rt[maxn];
     15 int tot, nex[maxm], fir[maxm], ver[maxm];
     16 int num, cnt;
     17 int ans;
     18 int disp[maxn];
     19 int si[maxn], dep[maxn], anc[maxn][logn + 1];
     20 int fat[maxn];
     21 int val[maxn];
     22 bool vis[maxn];
     23 inline int Get()
     24 {
     25     int x;
     26     char c;
     27     bool o = false;
     28     while((c = getchar()) < '0' || c > '9')
     29         if(c == '-') o = true;
     30     x = c - '0';
     31     while((c = getchar()) >= '0' && c <= '9')
     32         x = x * 10 + c - '0';
     33     return (o) ? -x : x;
     34 }
     35 inline void Reset()
     36 {
     37     for(int i = 1; i <= n; ++i)
     38         disp[i] = val[i], fat[i] = i, si[i] = 1;
     39 }
     40 inline void Disperse()
     41 {
     42     sort(disp + 1, disp + 1 + n);
     43     disp[0] = -inf;
     44     for(int i = 1; i <= n; ++i)
     45         if(disp[i] != disp[i - 1])
     46             disp[++num] = disp[i];
     47     for(int i = 1; i <= n; ++i)
     48         val[i] = lower_bound(disp + 1, disp + 1 + num, val[i]) - disp;
     49 }
     50 inline void Ins(int x, int y)
     51 {
     52     nex[++tot] = fir[x], fir[x] = tot, ver[tot] = y;
     53 }
     54 inline int Find(int x)
     55 {
     56     return (fat[x] != x) ? fat[x] = Find(fat[x]) : x;
     57 }
     58 inline void Edge(int x, int y)
     59 {
     60     int a = Find(x), b = Find(y);
     61     if(a != b) fat[a] = b, si[b] += si[a];
     62     Ins(x, y), Ins(y, x);
     63 }
     64 int Add(int p, int l, int r, int v)
     65 {
     66     int k = ++cnt;
     67     sum[k] = sum[p] + 1;
     68     if(l == r) return k;
     69     int mi = l + r >> 1;
     70     if(v <= mi) lc[k] = Add(lc[p], l, mi, v), rc[k] = rc[p];
     71     else lc[k] = lc[p], rc[k] = Add(rc[p], mi + 1, r, v);
     72     return k;
     73 }
     74 void Build(int u, int f)
     75 {
     76     vis[u] = true;
     77     dep[u] = dep[f] + 1;
     78     anc[u][0] = f;
     79     for(int i = 1; i <= logn; ++i)
     80         anc[u][i] = anc[anc[u][i - 1]][i - 1];
     81     rt[u] = Add(rt[f], 1, num, val[u]);
     82     for(int i = fir[u]; i; i = nex[i])
     83     {
     84         int v = ver[i];
     85         if(v == f) continue;
     86         Build(v, u);
     87     }
     88 }
     89 inline void Edge()
     90 {
     91     for(int i = 1; i <= m; ++i) Edge(Get(), Get());
     92 }
     93 inline void Build()
     94 {
     95     for(int i = 1; i <= n; ++i)
     96         if(!vis[i])
     97             Build(i, 0);
     98 }
     99 inline void Link(int x, int y)
    100 {
    101     int a = Find(x), b = Find(y);
    102     if(si[a] < si[b]) swap(x, y);
    103     dep[y] = dep[x] + 1;
    104     Build(y, x);
    105     Ins(x, y), Ins(y, x);
    106 }
    107 inline int Lca(int x, int y)
    108 {
    109     if(dep[x] < dep[y]) swap(x, y);
    110     for(int i = logn; i >= 0; --i)
    111         if(dep[anc[x][i]] >= dep[y])
    112             x = anc[x][i];
    113     if(x == y) return x;
    114     for(int i = logn; i >= 0; --i)
    115         if(anc[x][i] != anc[y][i])
    116         {
    117             x = anc[x][i];
    118             y = anc[y][i];
    119         }
    120     return anc[x][0];
    121 }
    122 inline int Query(int a, int b, int c, int d, int l, int r, int k)
    123 {
    124     if(l == r) return disp[l];
    125     int res = sum[lc[a]] + sum[lc[b]] - sum[lc[c]] - sum[lc[d]];
    126     int mi = l + r >> 1;
    127     if(res >= k) return Query(lc[a], lc[b], lc[c], lc[d], l, mi, k);
    128     return Query(rc[a], rc[b], rc[c], rc[d], mi + 1, r, k - res);
    129 }
    130 inline void Ask()
    131 {
    132     while(q--)
    133     {
    134         char c;
    135         while((c = getchar()) != 'L' && c != 'Q');
    136         switch(c)
    137         {
    138             case 'L':
    139             {
    140                 int x = Get() ^ ans, y = Get() ^ ans;
    141                 Link(x, y);
    142                 break;
    143             }
    144             case 'Q':
    145             {
    146                 int x = Get() ^ ans, y = Get() ^ ans, k = Get() ^ ans;
    147                 int lca = Lca(x, y);
    148                 ans = Query(rt[x], rt[y], rt[lca], rt[anc[lca][0]], 1, num, k);
    149                 printf("%d
    ", ans);
    150                 break;
    151             }
    152         }
    153     }
    154 }
    155 int main()
    156 {
    157     t = Get(), n = Get(), m = Get(), q = Get();
    158     for(int i = 1; i <= n; ++i) val[i] = Get();
    159     Reset();
    160     Disperse();
    161     Edge();
    162     Build();
    163     Ask();
    164 }
  • 相关阅读:
    Python(一)-基础不牢,地动山摇
    微信公众号开启企业付款到用户
    CSS多行显示省略号
    angular service自定义返回
    CSS input radio和checkbox样式
    angular微信支付url未注册
    angular+ionic的兼容性问题
    js 字符串和16进制的互相转换
    js循环变量赋值
    CSS 两层实现垂直居中(外层固定宽高,内层文本不定行数)
  • 原文地址:https://www.cnblogs.com/lytccc/p/6616589.html
Copyright © 2011-2022 走看看