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

    3123: [Sdoi2013]森林

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 2745  Solved: 808
    [Submit][Status][Discuss]

    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。之后的操作类似。 

     

    Source

     
    [Submit][Status][Discuss]

    首先,考虑一下如果没有加边操作,可以怎么做呢?主席树吧,每个点上挂一个版本,由树上父亲的版本修改而来,包含该点到根路径上所有点的权值信息。查询的时候只需要取出x,y上的答案,去掉lca(x,y),lca(x,y).father的答案即可得到x到y路径上的答案了。

    因为有加边操作,每次需要重新DFS处理主席树,按秩合并的思想,保留原本大小大的一棵树不变,重新DFS小的一棵即可。

    复杂度$O(Nlog^{2}N)$

     1 #include <bits/stdc++.h>
     2 const int siz = 200005, tre = 20000005;
     3 int n, m, q, val[siz], map[siz], tot, hd[siz], to[siz], nt[siz], edge, root[siz], ls[tre], rs[tre], sm[tre], cnt, vis[siz], fa[siz][25], dep[siz], bl[siz], sz[siz], qa[siz], qb[siz], tail;
     4 inline int find(int u) { return bl[u] == u ? u : bl[u] = find(bl[u]); }
     5 inline void Union(int a, int b) { a = find(a), b = find(b); if (a ^ b)bl[a] = b, sz[b] += sz[a]; }
     6 void insert(int &t, int f, int l, int r, int p) {
     7     t = ++cnt; ls[t] = ls[f], rs[t] = rs[f], sm[t] = sm[f] + 1;
     8     if (l != r) { int mid = (l + r) >> 1; (p <= mid ? insert(ls[t], ls[f], l, mid, p) : insert(rs[t], rs[f], mid + 1, r, p)); }
     9 }
    10 void dfs(int u, int f) { vis[u] = 1; 
    11     if (u && f)Union(u, f); 
    12     dep[u] = dep[f] + 1, fa[u][0] = f;
    13     insert(root[u], root[f], 1, tot, val[u]);
    14     for (int i = 1; i < 25; ++i)fa[u][i] = fa[fa[u][i - 1]][i - 1];
    15     for (int i = hd[u]; i; i = nt[i])if (to[i] != f)dfs(to[i], u);
    16 }
    17 inline int lca(int a, int b) {
    18     if (dep[a] < dep[b])a ^= b ^= a ^= b;
    19     for (int i = 24; ~i; --i)if (dep[fa[a][i]] >= dep[b])a = fa[a][i];
    20     for (int i = 24; ~i; --i)if (fa[a][i] ^ fa[b][i])a = fa[a][i], b = fa[b][i];
    21     return a == b ? a : fa[a][0];
    22 }
    23 inline void add(int a, int b) { qa[tail] = root[a], qb[tail++] = b; }
    24 int qry(int l, int r, int k) { if (l == r)return l; int s = 0, mid = (l + r) >> 1; 
    25     for (int i = 0; i < tail; ++i)s += qb[i] * sm[ls[qa[i]]];
    26     for (int i = 0; i < tail; ++i)qa[i] = s < k ? rs[qa[i]] : ls[qa[i]];
    27     return s < k ? qry(mid + 1, r, k - s) : qry(l, mid, k);
    28 }
    29 inline void adde(int x, int y) {
    30     nt[++edge] = hd[x], to[edge] = y, hd[x] = edge,
    31     nt[++edge] = hd[y], to[edge] = x, hd[y] = edge;
    32 }
    33 signed main(void) {
    34     scanf("%*d%d%d%d", &n, &m, &q);
    35     for (int i = 1; i <= n; ++i)scanf("%d", val + i), map[++tot] = val[i], sz[i] = 1, bl[i] = i;
    36     std::sort(map + 1, map + tot + 1); tot = std::unique(map + 1, map + tot + 1) - map;
    37     for (int i = 1; i <= n; ++i)val[i] = std::lower_bound(map + 1, map + tot, val[i]) - map;
    38     for (int i = 1, x, y; i <= m; ++i)scanf("%d%d", &x, &y), adde(x, y);
    39     for (int i = 1; i <= n; ++i)if (!vis[i])dfs(i, 0);
    40     for (int i = 1, ans = 0, x, y, k, t; i <= q; ++i) { char c = getchar(); while (c != 'Q' && c != 'L')c = getchar();
    41         if (c == 'L') { scanf("%d%d", &x, &y), x ^= ans, y ^= ans, adde(x, y); if (sz[find(x)] > sz[find(y)])dfs(y, x); else dfs(x, y); }
    42         else scanf("%d%d%d", &x, &y, &k), x ^= ans, y ^= ans, k ^= ans, tail = 0, 
    43         add(x, 1), add(y, 1), add(t = lca(x, y), -1), add(fa[t][0], -1), printf("%d
    ", ans = map[qry(1, tot, k)]);
    44     }
    45 }

    发现我代码写长了就有毒…… 300+代码无限RE中

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 
      6 inline char nextC(void)
      7 {
      8     static const int siz = 1024;
      9     
     10     static char buf[siz];
     11     static char *hd = buf + siz;
     12     static char *tl = buf + siz;
     13     
     14     if (hd == tl)
     15         fread(hd = buf, 1, siz, stdin);
     16         
     17     return *hd++;
     18 }
     19 
     20 inline int nextI(void)
     21 {
     22     register int ret = 0;
     23     register int neg = false;
     24     register int bit = nextC();
     25     
     26     for (; bit < 48; bit = nextC())
     27         if (bit == '-')neg ^= true;
     28         
     29     for (; bit > 47; bit = nextC())
     30         ret = ret * 10 + bit - 48;
     31         
     32     return neg ? -ret : ret;
     33 }
     34 
     35 inline bool nextO(void)
     36 {
     37     register char c = nextC();
     38     
     39     while (c != 'Q' && c != 'L')
     40         c = nextC();
     41         
     42     return c == 'Q';
     43 }
     44 
     45 const int siz = 1000005;
     46 
     47 int n, m, q;
     48 
     49 int val[siz];
     50 int map[siz], tot;
     51 
     52 inline void initMap(void)
     53 {
     54     tot = 0;
     55     
     56     for (int i = 1; i <= n; ++i)
     57         map[++tot] = val[i];
     58         
     59 //    printf("tot = %d
    ", tot);
     60 //    
     61 //    for (int i = 1; i < tot; ++i)
     62 //        printf("%d ", map[i]);
     63 //    puts("");
     64         
     65     using namespace std;
     66     
     67     sort(map + 1, map + tot + 1);
     68     
     69     tot = unique(map + 1, map + tot + 1) - map;
     70     
     71     for (int i = 1; i <= n; ++i)
     72         val[i] = lower_bound(map + 1, map + tot, val[i]) - map;
     73         
     74 //    printf("tot = %d
    ", tot);
     75 //    
     76 //    for (int i = 1; i < tot; ++i)
     77 //        printf("%d ", map[i]);
     78 //    puts("");
     79 }
     80 
     81 int edge;
     82 int hd[siz];
     83 int nt[siz];
     84 int to[siz];
     85 
     86 inline void initEdge(void)
     87 {
     88     edge = 0;
     89     memset(hd, -1, sizeof(hd));
     90 //    static int sz = sizeof(int);
     91 //    memset(hd, -1, sz * (n + 5));
     92 }
     93     
     94 
     95 inline void addEdge(int x, int y)
     96 {
     97     nt[edge] = hd[x]; to[edge] = y; hd[x] = edge++;
     98     nt[edge] = hd[y]; to[edge] = x; hd[y] = edge++;
     99 }
    100 
    101 int cnt;
    102 int root[siz];
    103 int ls[siz * 20];
    104 int rs[siz * 20];
    105 int sm[siz * 20];
    106 
    107 inline void initTree(void)
    108 {
    109     cnt = 0;
    110     memset(root, 0, sizeof(root));
    111 //    static int sz = sizeof(int);
    112 //    memset(root, 0, sz * (n + 5));
    113 }
    114 
    115 void insert(int &t, int f, int l, int r, int p, int v)
    116 {
    117     t = ++cnt;
    118     
    119     ls[t] = ls[f];
    120     rs[t] = rs[f];
    121     sm[t] = sm[f] + v;
    122     
    123 //    printf("%d %d %d %d
    ", t, l, r, sm[t]);
    124     
    125     if (l != r)
    126     {
    127         int mid = (l + r) >> 1;
    128         
    129         if (p <= mid)
    130             insert(ls[t], ls[f], l, mid, p, v);
    131         else
    132             insert(rs[t], rs[f], mid + 1, r, p, v);
    133     }
    134 }
    135 
    136 int fa[siz][25], dep[siz];
    137 
    138 inline void initLCA(void)
    139 {
    140     memset(dep, 0, sizeof(dep));
    141 //    static int sz = sizeof(int);
    142 //    memset(dep, 0, sz * (n + 5));
    143 }
    144 
    145 inline int lca(int a, int b)
    146 {
    147     if (dep[a] < dep[b])
    148         a ^= b ^= a ^= b;
    149         
    150     for (int i = 24; i >= 0; --i)
    151         if (dep[fa[a][i]] >= dep[b])
    152             a = fa[a][i];
    153     
    154     if (a == b)return a;
    155         
    156     for (int i = 24; i >= 0; --i)
    157         if (fa[a][i] != fa[b][i])
    158             a = fa[a][i],
    159             b = fa[b][i];
    160             
    161     return fa[a][0];
    162 }
    163 
    164 int f[siz], g[siz];
    165 
    166 inline void initUnion(void)
    167 {
    168     for (int i = 0; i <= n; ++i)
    169         f[i] = i, g[i] = 1;
    170 }
    171 
    172 inline int find(int u)
    173 {
    174     static int stk[siz], top = 0;
    175     
    176     while (f[u] != u)
    177         stk[++top] = u, u = f[u];
    178         
    179     while (top)
    180         f[stk[top--]] = u;
    181         
    182     return u;
    183 }
    184 
    185 inline void Union(int a, int b)
    186 {
    187     if (!a)return;
    188     if (!b)return;
    189     
    190     a = find(a);
    191     b = find(b);
    192     
    193     if (a != b)
    194     {
    195         g[b] += g[a];
    196         f[a] = b;
    197     }
    198 }
    199 
    200 void dfs(int u, int fr)
    201 {
    202 //    printf("debug: dfs %d %d
    ", u, fr);
    203     
    204     Union(u, fr);
    205     
    206     fa[u][0] = fr;
    207     
    208     dep[u] = dep[fr] + 1;
    209     
    210     for (int i = 1; i < 25; ++i)
    211         fa[u][i] = fa[fa[u][i - 1]][i - 1];
    212         
    213     insert(root[u], root[fr], 1, tot, val[u], 1);
    214         
    215     for (int i = hd[u]; ~i; i = nt[i])
    216         if (to[i] != fr)dfs(to[i], u);
    217 }
    218 
    219 int queA[siz], queB[siz], tail;
    220 
    221 inline void initQue(void)
    222 {
    223     tail = 0;
    224 }
    225 
    226 inline void addQue(int a, int b)
    227 {
    228     queA[tail] = root[a];
    229     queB[tail++] = b;
    230 }
    231 
    232 int query(int l, int r, int k)
    233 {
    234     if (l == r)return l;
    235     
    236     int s = 0, mid = (l + r) >> 1;
    237     
    238     for (int i = 0; i < tail; ++i)
    239         s += sm[ls[queA[i]]] * queB[i];
    240         
    241     if (s >= k)
    242     {
    243         for (int i = 0; i < tail; ++i)
    244             queA[i] = ls[queA[i]];
    245             
    246         return query(l, mid, k);
    247     }
    248     else
    249     {
    250         for (int i = 0; i < tail; ++i)
    251             queA[i] = rs[queA[i]];
    252             
    253         return query(mid + 1, r, k - s);
    254     }
    255 }
    256 
    257 int ans;
    258 
    259 signed main(void)
    260 {
    261     for (int cas = nextI(); cas--; )
    262     {
    263         n = nextI();
    264         m = nextI();
    265         q = nextI();
    266         
    267         for (int i = 1; i <= n; ++i)
    268             val[i] = nextI();
    269         
    270         initMap();
    271         initEdge();
    272         initTree();
    273         initUnion();
    274         
    275         for (int i = 1; i <= m; ++i)
    276         {
    277             int x = nextI();
    278             int y = nextI();
    279             addEdge(x, y);
    280         }
    281         
    282         for (int i = 1; i <= n; ++i)
    283             if (g[find(i)] == 1)
    284                 dfs(i, 0);
    285         
    286 //        puts("debug: prework finished");
    287                 
    288         for (int i = 1; i <= q; ++i)
    289         {
    290             if (nextO())    // Query
    291             {
    292                 int x = nextI() ^ ans;
    293                 int y = nextI() ^ ans;
    294                 int k = nextI() ^ ans;
    295                 
    296                 int t = lca(x, y);
    297                 
    298 //                printf("debug: lca %d %d = %d
    ", x, y, t);
    299                 
    300                 initQue();
    301                 
    302                 addQue(x, +1);
    303                 addQue(y, +1);
    304                 addQue(t, -1);
    305                 addQue(fa[t][0], -1);
    306                 
    307 //                for (int i = 0; i < tail; ++i)
    308 //                    printf("que %d %d
    ", queA[i], queB[i]);
    309                 
    310                 printf("%d
    ", ans = map[query(1, tot, k)]);
    311             }
    312             else    // Link
    313             {
    314                 int x = nextI() ^ ans;
    315                 int y = nextI() ^ ans;
    316                 
    317                 if (g[find(x)] > g[find(y)])
    318                     dfs(y, x);
    319                 else
    320                     dfs(x, y);
    321             }
    322         }
    323     }
    324 }
    325 /*
    326 1
    327 8 4 8
    328 1 1 2 2 3 3 4 4
    329 4 7
    330 1 8
    331 2 4
    332 2 1
    333 Q 8 7 3 
    334 Q 3 5 1 
    335 Q 10 0 0 
    336 L 5 4 
    337 L 3 2 
    338 L 0 7 
    339 Q 9 2 5 
    340 Q 6 1 6
    341 */
    View Code

    @Author: YouSiki

  • 相关阅读:
    vue基础笔记
    HM.DAY-02
    前端基础(三)
    前端基础 (二)
    前端基础(一)
    爬虫基础入门(二)
    爬虫基础入门(一)
    Python进阶(三)
    Python进阶(二)
    python切片
  • 原文地址:https://www.cnblogs.com/yousiki/p/6268515.html
Copyright © 2011-2022 走看看