• BZOJ 1969 航线规划


    Solution

    实际上就是查询 $u$ 到 $v$ 路径上 边双的个数 $ -1$。

    并且题目仅有删边, 那么就离线倒序添边。

    维护 边双 略有不同: 

    首先需要一个并查集, 记录 边双内的点。 在 添加边$(u,v)$时 , 若$u, v$ 已经相连, 那么把 $u, v$ 路径上的点 缩成一个点, 用最上面的点 来代替。

    1 void del(int x, int y) {
    2         if (!x) return;
    3         fa[x] = y;
    4         del(lc(x), y);
    5         del(rc(x), y);
    6     }
    压缩点

    access 也应该变化 : $f[x]$ 可能已经经过压缩了。

    1 void access(int x) {
    2         for (int y = 0; x; y = x, x = f[y] = anc(f[x]))
    3             splay(x), ch[x][1] = y, up(x);
    4     }
    access

    Code

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define rd read()
      5 using namespace std;
      6 
      7 const int N = 3e4 + 5;
      8 const int M = 1e5 + 5;
      9 
     10 int n, m;
     11 int fa[N], ans[N], vis[M];
     12 
     13 struct edge {
     14     int u, v;
     15 
     16     bool operator < (const edge &b) const {
     17         return u == b.u ? v < b.v : u < b.u;
     18     }
     19 }e[M];
     20 
     21 struct que {
     22     int op, u, v;
     23 }q[M];
     24 
     25 int read() {
     26     int X = 0, p = 1; char c = getchar();
     27     for (; c > '9' || c < '0'; c = getchar())
     28         if (c == '-') p = -1;
     29     for (; c >= '0' && c <= '9'; c = getchar())
     30         X = X * 10 + c - '0';
     31     return X * p;
     32 }
     33 
     34 int anc(int x) {
     35     return fa[x] == x? x : fa[x] = anc(fa[x]);
     36 }
     37 
     38 namespace LCT {
     39     int f[N], sz[N], ch[N][2], tun[N];
     40 #define lc(x) ch[x][0]
     41 #define rc(x) ch[x][1]
     42 
     43     int isroot(int x) {
     44         return rc(f[x]) != x && lc(f[x]) != x;
     45     }
     46 
     47     int get(int x) {
     48         return rc(f[x]) == x;
     49     }
     50 
     51     void rev(int x) {
     52         swap(lc(x), rc(x));
     53         tun[x] ^= 1;
     54     }
     55 
     56     void up(int x) {
     57         sz[x] = 1;
     58         if (lc(x)) sz[x] += sz[lc(x)];
     59         if (rc(x)) sz[x] += sz[rc(x)];
     60     }
     61 
     62     void pushdown(int x) {
     63         if (tun[x]) {
     64             if (lc(x)) rev(lc(x));
     65             if (rc(x)) rev(rc(x));
     66             tun[x] = 0;
     67         }
     68     }
     69 
     70     void pd(int x) {
     71         if (!isroot(x))
     72             pd(f[x]);
     73         pushdown(x);
     74     }
     75 
     76     void rotate(int x) {
     77         int old = f[x], oldf = f[old], son = ch[x][get(x) ^ 1];
     78         if (!isroot(old)) ch[oldf][get(old)] = x;
     79         ch[x][get(x) ^ 1] = old;
     80         ch[old][get(x)] = son;
     81         f[son] = old; f[x] = oldf; f[old] = x;
     82         up(old); up(x);
     83     }
     84 
     85     void splay(int x) {
     86         pd(x);
     87         for (; !isroot(x); rotate(x))
     88             if (!isroot(f[x]))
     89                 rotate(get(f[x]) == get(x) ? f[x] : x);
     90     }
     91     
     92     void access(int x) {
     93         for (int y = 0; x; y = x, x = f[y] = anc(f[x]))
     94             splay(x), ch[x][1] = y, up(x);
     95     }
     96 
     97     int findr(int x) {
     98         access(x); splay(x);
     99         while (lc(x)) pushdown(x), x = lc(x);
    100         return x;
    101     }
    102 
    103     void mroot(int x) {
    104         access(x); splay(x); rev(x);
    105     }
    106 
    107     void split(int x, int y) {
    108         mroot(x); access(y); splay(y);
    109     }
    110 
    111     void del(int x, int y) {
    112         if (!x) return;
    113         fa[x] = y;
    114         del(lc(x), y);
    115         del(rc(x), y);
    116     }
    117 
    118     void link(int x, int y) {
    119         mroot(x);
    120         f[x] = y;
    121     }
    122 
    123     void merge(int x, int y) {
    124         x = anc(x); y = anc(y);
    125         if (x == y)
    126             return;
    127         mroot(x);
    128         if (findr(y) != x) 
    129             link(x, y);
    130         else {
    131             splay(x);
    132             del(rc(x), x);
    133             rc(x) = 0; up(x);
    134         }
    135     }
    136 }
    137 
    138 using namespace LCT;
    139 
    140 int main()
    141 {
    142     n = rd; m = rd;
    143     for (int i = 1; i <= n; ++i)
    144         fa[i] = i;
    145     for (int i = 1; i <= m; ++i) {
    146         e[i].u = rd; e[i].v = rd;
    147         if (e[i].u > e[i].v)
    148             swap(e[i].u, e[i].v);
    149     }
    150     sort(e + 1, e + 1 + m);
    151     int Q = 0;
    152     for (; ; ) {
    153         int op = rd;
    154         if (op == -1)
    155             break;
    156         int u = rd, v = rd;
    157         if (u > v)
    158             swap(u, v);
    159         q[++Q].op = op; q[Q].u = u;
    160         q[Q].v = v;
    161         edge t;
    162         t.u = u; t.v = v;
    163         if (op == 0)
    164             vis[lower_bound(e + 1, e + 1 + m, t) - e] = 1;
    165     }
    166     for (int i = 1; i <= m; ++i)
    167         if (!vis[i]) 
    168             merge(e[i].u, e[i].v);
    169     for (int i = Q; i; i--) {
    170         if (q[i].op == 1) {
    171             int x = q[i].u, y = q[i].v;
    172             x = anc(x); y = anc(y);
    173             if (x == y) {ans[i] = 0; continue;}
    174             split(x, y);
    175             ans[i] = sz[y] - 1;
    176         }
    177         else merge(q[i].u, q[i].v);
    178     }
    179     for (int i = 1; i <= Q; ++i)
    180         if (q[i].op == 1)
    181             printf("%d
    ", ans[i]);
    182 }
    View Code
  • 相关阅读:
    【接口平台】上报接口处理时间
    【性能测试】吞吐量上不去的问题
    vue层级选择器多选
    打家劫舍 II
    打家劫舍
    房屋染色 II
    距离顺序排列矩阵单元格
    根据身高重建队列
    将 x 减到 0 的最小操作数
    确定两个字符串是否接近
  • 原文地址:https://www.cnblogs.com/cychester/p/9698979.html
Copyright © 2020-2023  润新知