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

    Description

    给你一片森林, 支持两个操作: 查询$x$到$y$的$K$大值,  连接两棵树中的两个点

    Solution

    对每个节点$x$动态开权值线段树, 表示从$x$到根节点路径上权值出现的次数。

    查询时差分即可: $sum[x]+sum[y]-sum[lca]-sum[f[lca]]$

    连边时需要启发式合并,将节点数小的接到节点数大的上去, 再遍历小的树, 并更新权值

     

    我刚开始以为testcase是数据组数, TLE我好久,,

    Code

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define rd read()
      5 using namespace std;
      6 
      7 const int N = 1e5;
      8 
      9 int lson[N * 100], rson[N * 100], sum[N * 100], root[N];
     10 int n, m, T, a[N], b[N], f[N][25], head[N], tot, dep[N];
     11 int father[N], num[N], cnt, nd_num;
     12 int lastans, Case; 
     13 
     14 struct edge {
     15     int nxt, to;
     16 }e[N << 2];
     17 
     18 int read() {
     19     int X = 0, p = 1; char c = getchar();
     20     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
     21     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
     22     return X * p;
     23 }
     24 
     25 void add(int u, int v) {
     26     e[++tot].to = v;
     27     e[tot].nxt = head[u];
     28     head[u] = tot;
     29 }
     30 
     31 int find_anc(int x) {
     32     return father[x] == x ? x : father[x] = find_anc(father[x]);
     33 }
     34 
     35 int find_lca(int x, int y) {
     36     if(dep[x] < dep[y]) swap(x, y);
     37     for(int i = 20; ~i; --i) if(dep[f[x][i]] >= dep[y])
     38         x = f[x][i];
     39     if(x == y) return x;
     40     for(int i = 20; ~i; --i) if(f[x][i] != f[y][i])
     41         x = f[x][i], y = f[y][i];
     42     return f[x][0];
     43 }
     44 
     45 int fd(int x) {
     46     return lower_bound(b + 1, b + 1 + cnt, x) - b;
     47 }
     48 
     49 void ins(int &o, int now, int l, int r, int pos) {
     50     o = ++nd_num;
     51     sum[o] = sum[now] + 1;
     52     lson[o] = lson[now];
     53     rson[o] = rson[now];
     54     if(l == r) return;
     55     int mid = (l + r) >> 1;
     56     if(pos <= mid) ins(lson[o], lson[now], l, mid, pos);
     57     else ins(rson[o], rson[now], mid + 1, r, pos);
     58 }
     59 
     60 int query(int x, int y, int lca, int flca, int l, int r, int k) {
     61     if(l == r) return l;
     62     int mid = (l + r) >> 1, tmp;
     63     if((tmp = sum[lson[x]] + sum[lson[y]] - sum[lson[lca]] - sum[lson[flca]]) >= k) return query(lson[x], lson[y], lson[lca], lson[flca], l, mid, k);
     64     else return query(rson[x], rson[y], rson[lca], rson[flca], mid + 1, r, k - tmp);
     65 }
     66 
     67 void dfs(int u) {
     68     dep[u] = dep[f[u][0]] + 1;
     69     for(int i = 1; i <= 20; ++i)
     70         f[u][i] = f[f[u][i - 1]][i - 1];
     71     ins(root[u], root[f[u][0]], 1, cnt, fd(a[u]));
     72     for(int i = head[u]; i; i = e[i].nxt) {
     73         int nt = e[i].to;
     74         if(nt == f[u][0]) continue;
     75         f[nt][0] = u;
     76         dfs(nt);
     77     }
     78 }
     79 
     80 int work() {
     81     lastans = 0; tot = 0;
     82     nd_num = 0;
     83 /*    memset(root, 0, sizeof(root));
     84     memset(lson, 0, sizeof(lson));
     85     memset(rson, 0, sizeof(rson));
     86     memset(head, 0, sizeof(head));
     87     memset(dep, 0, sizeof(dep));*/
     88     n = rd; m = rd; T = rd;
     89     for(int i = 1; i <= n; ++i) b[i] = a[i] = rd;
     90     sort(b + 1, b + 1 + n);
     91     cnt = unique(b + 1, b + 1 + n) - b - 1;
     92     for(int i = 1; i <= n; ++i) father[i] = i, num[i] = 1;
     93     for(int i = 1; i <= m; ++i) {
     94         int u = rd, v = rd;
     95         int x = find_anc(u), y = find_anc(v);
     96         father[y] = x;
     97         num[x] += num[y];
     98         add(u, v); add(v, u);
     99     }
    100     for(int i = 1; i <= n; ++i) if(!dep[i]) dfs(i);
    101     for(int i = 1; i <= T; ++i) {
    102         char c = getchar();
    103         while(c != 'Q' && c != 'L') c = getchar();
    104         int u = rd ^ lastans, v = rd ^ lastans;
    105         if(c == 'Q') {
    106             int lca = find_lca(u, v), flca = f[lca][0], k = rd ^ lastans;
    107             lastans = query(root[u], root[v], root[lca], root[flca], 1, cnt, k);
    108             if(lastans > cnt || lastans < 0) return printf("F**k,WA
    "), 0;
    109             lastans = b[lastans];
    110             printf("%d
    ", lastans);
    111         }
    112         else {
    113             int x = find_anc(u), y = find_anc(v);
    114             if(num[x] < num[y]) {
    115                 swap(x, y); swap(u, v);
    116             }
    117             father[y] = x;
    118             num[x] += num[y];
    119             f[v][0] = u;
    120             add(v, u); add(u, v);
    121             dfs(v);
    122         }
    123     }
    124     return 0;
    125 }
    126 
    127 int main()
    128 {
    129     Case = rd;
    130     work();
    131 }
    View Code
  • 相关阅读:
    GO 语言使用copy 拷贝切片的问题
    ggplot 局部放大
    R语言hist重叠图作法
    illumina SNP 芯片转基因型矩阵
    Shell 变量嵌套
    JVM指令
    VUE—CLI学习
    Gradle 项目打开自动下载Zip问题及相关配置
    MySQL8服务无法启动,服务没有报告任何错误
    SpringMVC相关
  • 原文地址:https://www.cnblogs.com/cychester/p/9621163.html
Copyright © 2011-2022 走看看