• bzoj 3123[Sdoi2013]森林


    3123: [Sdoi2013]森林

    Time Limit: 20 Sec  Memory Limit: 512 MB

    Description

    Input

    第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。 
    第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。 
     接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

    Output

    对于每一个第一类操作,输出一个非负整数表示答案。 
     
     

    Sample Input

    1
    8 4 8
    1 1 2 2 3 3 4 4
    4 7
    1 8
    2 4
    2 1
    Q 8 7 3 Q 3 5 1
    Q 10 0 0
    L 5 4
    L 3 2 L 0 7
    Q 9 2 5 Q 6 1 6

    Sample Output

    2
    2
    1
    4
    2

    HINT



    对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。这些权值中,第三小的为 2,输出 2,lastans变为2。对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。 

     

    一道树上主席树的练习题

    查询x-y的链的大小时,我们的思路都是二分权值,但此时是以每一个树的节点为根,因此x-y这条链上的信息就等于

    root[x] + root[y] - root[lca(x, y)] - root[fa(lca(x, y))]

    每一个节点的线段树都对应的是点到根的路径信息

    合并就是启发式合并的操作,暴力加点

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <cmath>
      6 #define LL long long
      7 #define lc seg[x].ch[0]
      8 #define rc seg[x].ch[1]
      9 
     10 using namespace std;
     11 
     12 
     13 const int MAXN = 8e4 + 10, MAXM = 8e4 + 10;
     14 int N, M, T;
     15 int SIZE = 0;
     16 LL ans;
     17 LL lastans = 0;
     18 int sum;
     19 int size[MAXN];
     20 int cnt = 0;
     21 int tot = 0;
     22 int root[MAXN];
     23 int deep[MAXN];
     24 int ra[MAXN];
     25 int val[MAXN];
     26 int head[MAXN];
     27 int testcase;
     28 int fa[30][MAXN];
     29 int father[MAXN];
     30 char opr[10];
     31 
     32 struct node {
     33     int val;
     34     int id;
     35 } n[MAXN];
     36 
     37 inline LL read()
     38 {
     39     LL x = 0, w = 1; char ch = 0;
     40     while(ch < '0' || ch > '9') {
     41         if(ch == '-') {
     42             w = -1;
     43         }
     44         ch = getchar();
     45     }
     46     while(ch >= '0' && ch <= '9') {
     47         x = x * 10 + ch - '0';
     48         ch = getchar();
     49     }
     50     return x * w;
     51 }
     52 
     53 struct segment {
     54     int ch[2];
     55     int num;
     56 } seg[MAXN * 200];
     57 
     58 int find(int x)
     59 {
     60     if(x != father[x]) {
     61         x = find(father[x]);
     62     }
     63     return father[x];
     64 }
     65 
     66 void pushup(int x)
     67 {
     68     seg[x].num = seg[lc].num + seg[rc].num;
     69 }
     70 
     71 struct edge {
     72     int v;
     73     int next;
     74 } g[MAXN * 10];
     75 
     76 void addedge(int u, int v)
     77 {
     78     g[++cnt].v = v;
     79     g[cnt].next = head[u];
     80     head[u] = cnt;
     81 }
     82 
     83 void init()
     84 {
     85     for(int i = 1; i < MAXN; i++) {
     86         father[i] = i;
     87     }
     88 }
     89 
     90 void multify()
     91 {
     92     for(int j = 1; j < 20; j++) {
     93         for(int i = 1; i <= N; i++) {
     94             fa[j][i] = fa[j - 1][fa[j - 1][i]];
     95         }
     96     }
     97 }
     98 
     99 void insert(int l, int r, int &x, int k)
    100 {
    101     seg[++tot] = seg[x];
    102     x = tot;
    103     if(l == r) {
    104         seg[x].num++;
    105         return;
    106     }
    107     int mid = (l + r) >> 1;
    108     if(k > mid) {
    109         insert(mid + 1, r, rc, k);
    110     } else {
    111         insert(l, mid, lc, k);
    112     }
    113     pushup(x);
    114 }
    115 
    116 void build(int x, int top)
    117 {
    118     sum++;
    119     father[x] = top;
    120     deep[x] = deep[fa[0][x]] + 1;
    121     root[x] = root[fa[0][x]];
    122     insert(1, SIZE, root[x], ra[x]);
    123     for(int j = head[x]; j; j = g[j].next) {
    124         int to = g[j].v;
    125         if(fa[0][to] == 0 && to != top) {
    126             fa[0][to] = x;
    127             build(to, top);
    128         }
    129     }
    130 }
    131 
    132 void merge(int x, int f)
    133 {
    134     fa[0][x] = f;
    135     deep[x] = deep[fa[0][x]] + 1;
    136     for(int j = 1; j < 20; j++) {
    137         fa[j][x] = fa[j - 1][fa[j - 1][x]];
    138     }
    139     root[x] = root[fa[0][x]];
    140     insert(1, SIZE, root[x], ra[x]);
    141     for(int j = head[x]; j; j = g[j].next) {
    142         int to = g[j].v;
    143         if(to != f) {
    144             merge(to, x);
    145         }
    146     }
    147 }
    148 
    149 void print(int l, int r, int x)
    150 {
    151     cout<<l<<" "<<r<<" "<<seg[x].num<<endl;
    152     if(l == r) {
    153         return;
    154     }
    155     int mid = (l + r) >> 1;
    156     print(l, mid, lc);
    157     print(mid + 1, r, rc);
    158 }
    159 
    160 bool cmp(node a, node b)
    161 {
    162     return a.val < b.val;
    163 }
    164 
    165 int get_lca(int x, int y)
    166 {
    167     if(deep[x] < deep[y]) {
    168         swap(x, y);
    169     }
    170     for(int j = 20; j >= 0; j--) {
    171         if(deep[fa[j][x]] >= deep[y]) {
    172             x = fa[j][x];
    173         }
    174     }
    175     if(x == y) {
    176         return x;
    177     }
    178     for(int j = 20; j >= 0; j--) {
    179         if(fa[j][x] != fa[j][y]) {
    180             x = fa[j][x], y = fa[j][y];
    181         }
    182     }
    183     return fa[0][x];
    184 }
    185 
    186 void query(int l, int r, int x, int y, int lca, int fca, int k)
    187 {
    188     if(l == r) {
    189         ans = val[l];
    190         return;
    191     }
    192     int mid = (l + r) >> 1;
    193     int NUM = seg[seg[x].ch[0]].num + seg[seg[y].ch[0]].num - seg[seg[lca].ch[0]].num - seg[seg[fca].ch[0]].num;
    194     if(NUM >= k) {
    195         query(l, mid, seg[x].ch[0], seg[y].ch[0], seg[lca].ch[0], seg[fca].ch[0], k);
    196     } else {
    197         query(mid + 1, r, seg[x].ch[1], seg[y].ch[1], seg[lca].ch[1], seg[fca].ch[1], k - NUM);
    198     }
    199 }
    200 
    201 int main()
    202 {
    203     init();
    204     testcase = read();
    205     N = read(), M = read(), T = read();
    206     for(int i = 1; i <= N; i++) {
    207         n[i].val = read();
    208         n[i].id = i;
    209     }
    210     sort(n + 1, n + 1 + N, cmp);
    211     ra[n[1].id] = SIZE = 1;
    212     val[1] = n[1].val;
    213     for(int i = 2; i <= N; i++) {
    214         if(n[i].val == n[i - 1].val) {
    215             ra[n[i].id] = SIZE;
    216         } else {
    217             ra[n[i].id] = ++SIZE;
    218             val[SIZE] = n[i].val;
    219         }
    220     }
    221     for(int i = 1; i <= M; i++) {
    222         int u = read(), v = read();
    223         addedge(u, v);
    224         addedge(v, u);
    225     }
    226     for(int i = 1; i <= N; i++) {
    227         sum = 0;
    228         if(fa[0][i] == 0)
    229             build(i, i);
    230         size[i] = sum;
    231     }
    232     /*cout<<endl;
    233     for(int i = 1; i <= N; i++) {
    234         cout<<ra[i]<<" "<<val[i]<<endl; 
    235     }*/
    236 //    return 0;
    237     multify();
    238     /*cout<<endl;
    239     for(int i = 1; i <= N; i++) {
    240         cout<<fa[0][i]<<" "<<father[i]<<endl; 
    241     }
    242     for(int i = 1; i <= N; i++) {
    243         cout<<i<<endl;
    244         print(1, SIZE, root[i]);
    245         cout<<endl<<endl;
    246     }
    247     return 0;*/
    248     for(int i = 1; i <= T; i++) {
    249         scanf("%s", opr);
    250         if(opr[0] == 'Q') {
    251             int x = read(), y = read(), k = read();
    252             x = x ^ lastans, y = y ^ lastans, k = k ^ lastans; 
    253         //    cout<<x<<" "<<y<<" "<<k<<endl;
    254             int lca = get_lca(x, y); 
    255             query(1, SIZE, root[x], root[y], root[lca], root[fa[0][lca]], k);
    256             printf("%lld
    ", ans);
    257             lastans = ans;
    258         } else {
    259             int x = read(), y = read();
    260             x = x ^ lastans, y = y ^ lastans;
    261         //    cout<<x<<" "<<y<<endl; 
    262             int u = find(x), v = find(y);
    263         //    cout<<u<<" "<<v<<" "<<size[u]<<" "<<size[v]<<endl;
    264             addedge(x, y);
    265             addedge(y, x);
    266             if(size[u] > size[v]) {
    267                 size[u] += size[v];
    268                 father[v] = u;
    269                 merge(y, x);
    270             } else {
    271                 size[v] += size[u];
    272                 father[u] = v;
    273                 merge(x, y);
    274             }
    275                 //cout<<i<<endl;
    276             //    print(1, SIZE, root[16]);
    277             //    cout<<endl<<endl;
    278             //    return 0;
    279         }
    280     }
    281 }
    282 
    283 /*
    284 1
    285 20 12 20
    286 412060525 42425138 67114752 160822495 201962681 926214957 380263349 733667141 869039239 641017702 154667400 461702107 438851950 176272938 209229857 985208975 762952138 936593832 409183276 999506034
    287 2 17
    288 4 1
    289 15 3
    290 3 10
    291 9 10
    292 7 16
    293 19 15
    294 13 2
    295 6 2
    296 3 14
    297 7 18
    298 8 15
    299 Q 6 17 2
    300 Q 762952152 762952154 762952139
    301 L 380263329 380263352
    302 L 380263357 380263333
    303 Q 380263356 380263359 380263348
    304 L 641017709 641017703
    305 L 641017716 641017700
    306 Q 641017716 641017704 641017698
    307 Q 380263359 380263357 380263345
    308 L 733667140 733667136
    309 L 733667150 733667156
    310 L 733667145 733667142
    311 Q 733667149 733667145 733667140
    312 Q 67114772 67114761 67114759
    313 Q 733667145 733667159 733667142
    314 Q 380263359 380263356 380263351
    315 Q 869039233 869039232 869039237
    316 Q 380263359 380263345 380263356
    317 Q 733667136 733667140 733667143
    318 Q 412060537 412060516 412060519
    319 */
    View Code
  • 相关阅读:
    redis集群搭建
    mybatis逆向工程--自动生成实体代码(mybatis-generator)
    设置启用mysql慢查询日志
    mysql 删除重复数据
    Vue自定义指令--开发一个可从外部关闭的下拉菜单
    《Vue.js实战》章七 组件——标签页组件:思路详解
    《Vue.js实战》章七 组件——数字输入框组件
    托管在github上的个人简历、静态网页里的音乐播放器,暂停、下一首、顺序播放
    2019.5.24 自学前端 120天
    《超实用的jQuery代码段》-3:计算加载时间、模拟抽奖、规定年龄计算、通用的清空表格函数
  • 原文地址:https://www.cnblogs.com/wuenze/p/9151039.html
Copyright © 2020-2023  润新知