• 洛谷P3302 森林


    题意:给定森林,可以把两棵树连起来或者询问链上第k大。

    解:启发式合并。

    我一开始想到了启发式合并但是发现这样做之后一棵子树就不是一段连续的区间了,那就不能子树xxx了,很迷惘。

    后来看了题解发现本来就不需要子树是连续区间......

    每次把小的树暴力DFS重构fa[][]和重建主席树。

    调了半天是因为lastans没有套上X[]......

    注意并查集merge的时候可能有元素为0。无视之即可。

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 const int N = 80010, M = 30000010;
      5 
      6 struct Edge {
      7     int nex, v;
      8 }edge[N << 1]; int top;
      9 
     10 int X[N], e[N], n, val[N], temp, pw[N], fa[N][20], tot, vis[N], father[N], siz[N], d[N], rt[N];
     11 int sum[M], ls[M], rs[M];
     12 char str[3];
     13 
     14 int find(int x) {
     15     if(father[x] == x) {
     16         return x;
     17     }
     18     return father[x] = find(father[x]);
     19 }
     20 
     21 inline void merge(int x, int y) {
     22     if(!x || !y) {
     23         return;
     24     }
     25     x = find(x);
     26     y = find(y);
     27     if(x == y) {
     28         return;
     29     }
     30     father[x] = y;
     31     siz[y] += siz[x];
     32     return;
     33 }
     34 
     35 inline bool check(int x, int y) {
     36     return find(x) == find(y);
     37 }
     38 
     39 inline void add(int x, int y) {
     40     top++;
     41     edge[top].v = y;
     42     edge[top].nex = e[x];
     43     e[x] = top;
     44     return;
     45 }
     46 
     47 void add(int x, int &y, int p, int l, int r) {
     48     if(!y || y == x) {
     49         y = ++tot;
     50         sum[y] = sum[x];
     51         ls[y] = ls[x];
     52         rs[y] = rs[x];
     53     }
     54     if(l == r) {
     55         sum[y]++;
     56         return;
     57     }
     58     int mid = (l + r) >> 1;
     59     if(p <= mid) {
     60         add(ls[x], ls[y], p, l, mid);
     61     }
     62     else {
     63         add(rs[x], rs[y], p, mid + 1, r);
     64     }
     65     sum[y] = sum[ls[y]] + sum[rs[y]];
     66     return;
     67 }
     68 
     69 void DFS(int x, int f) {
     70     merge(x, f);
     71     vis[x] = 1;
     72     fa[x][0] = f;
     73     d[x] = d[f] + 1;
     74     for(int j = 1; j <= pw[n]; j++) {
     75         fa[x][j] = fa[fa[x][j - 1]][j - 1];
     76     }
     77     rt[x] = 0;
     78     add(rt[f], rt[x], val[x], 1, temp);
     79     for(int i = e[x]; i; i = edge[i].nex) {
     80         int y = edge[i].v;
     81         if(y == f) {
     82             continue;
     83         }
     84         DFS(y, x);
     85     }
     86     return;
     87 }
     88 
     89 inline void link(int x, int y) {
     90     if(check(x, y)) {
     91         printf("E1");
     92         exit(0);
     93     }
     94     if(siz[find(x)] < siz[find(y)]) {
     95         std::swap(x, y);
     96     }
     97     DFS(y, x);
     98     add(x, y);
     99     add(y, x);
    100     return;
    101 }
    102 
    103 inline int lca(int x, int y) {
    104     if(d[x] > d[y]) {
    105         std::swap(x, y);
    106     }
    107     int t = pw[n];
    108     while(t >= 0 && d[x] != d[y]) {
    109         if(d[fa[y][t]] >= d[x]) {
    110             y = fa[y][t];
    111         }
    112         t--;
    113     }
    114     if(x == y) {
    115         return x;
    116     }
    117     t = pw[n];
    118     while(t >= 0 && fa[x][0] != fa[y][0]) {
    119         if(fa[x][t] != fa[y][t]) {
    120             x = fa[x][t];
    121             y = fa[y][t];
    122         }
    123         t--;
    124     }
    125     return fa[x][0];
    126 }
    127 
    128 int Ask(int x, int y, int z, int w, int k, int l, int r) {
    129     if(l == r) {
    130         return r;
    131     }
    132     int mid = (l + r) >> 1, s = 0;
    133     s = sum[ls[x]] + sum[ls[y]] - sum[ls[z]] - sum[ls[w]];
    134     if(k <= s) {
    135         return Ask(ls[x], ls[y], ls[z], ls[w], k, l, mid);
    136     }
    137     else {
    138         return Ask(rs[x], rs[y], rs[z], rs[w], k - s, mid + 1, r);
    139     }
    140 }
    141 
    142 inline int ask(int x, int y, int k) {
    143     if(!check(x, y)) {
    144         printf("E2");
    145         exit(0);
    146     }
    147     int z = lca(x, y);
    148     if(d[x] + d[y] - d[z] - d[z] + 1 < k) {
    149         printf("E3");
    150         exit(0);
    151     }
    152     return Ask(rt[x], rt[y], rt[z], rt[fa[z][0]], k, 1, temp);
    153 }
    154 
    155 int main() {
    156 
    157     //freopen("in.in", "r", stdin);
    158     //freopen("my.out", "w", stdout);
    159 
    160     int m, q;
    161     scanf("%d", &n);
    162     scanf("%d%d%d", &n, &m, &q);
    163     for(int i = 1; i <= n; i++) {
    164         scanf("%d", &val[i]);
    165         X[++temp] = val[i];
    166         siz[i] = 1;
    167         father[i] = i;
    168     }
    169     for(int i = 1, x, y; i <= m; i++) {
    170         scanf("%d%d", &x, &y);
    171         add(x, y);
    172         add(y, x);
    173     }
    174     for(int i = 2; i <= n; i++) {
    175         pw[i] = pw[i >> 1] + 1;
    176     }
    177     std::sort(X + 1, X + temp + 1);
    178     temp = std::unique(X + 1, X + temp + 1) - X - 1;
    179     for(int i = 1; i <= n; i++) {
    180         val[i] = std::lower_bound(X + 1, X + temp + 1, val[i]) - X;
    181     }
    182     for(int i = 1; i <= n; i++) {
    183         if(!vis[i]) {
    184             DFS(i, 0);
    185         }
    186     }
    187     /// build
    188 
    189     int lastans = 0;
    190     for(int i = 1, x, y, k; i <= q; i++) {
    191         scanf("%s%d%d", str, &x, &y);
    192         if(str[0] == 'L') { // link
    193             link(x ^ lastans, y ^ lastans);
    194         }
    195         else {
    196             scanf("%d", &k);
    197             lastans = X[ask(x ^ lastans, y ^ lastans, k ^ lastans)];
    198             printf("%d
    ", lastans);
    199         }
    200     }
    201 
    202     return 0;
    203 }
    AC代码
  • 相关阅读:
    屏蔽鼠标右键/F1帮助
    vs2010如何连接到mysql数据库
    经典的数据库设计贴吧
    js子窗口刷新父窗口
    数据库三大范式
    写给毕业生
    SQL Server权限数据库设计
    .NET
    ASP.NET MVC框架(第一部分) 【转】
    什么是SQL注入法攻击 .
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10324992.html
Copyright © 2020-2023  润新知