bzoj2594 [Wc2006]水管局长数据加强版

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2594

【题解】

不难考虑到这样一个性质:u->v路径上最大边最小,一定在MST上。

这个可以用kruskal来证明

有了这个结论就这题很显然就可做了。

考虑时光倒流,变成加边、询问u->v路径上最大边最小值。

可以用LCT维护边权最大值以及出现位置,即可。

复杂度$O(nlog(n+m))$。

竟然1A了。。还刚好25s。感觉非常优秀。

竟然只写了20min,代码可读性很高

# include 
# include 
# include <string.h>
# include 
# include 
// # include 

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1.5e6 + 10, N = 1e5 + 10;
const int mod = 1e9+7;

// 性质:u->v路径上最大边最小,一定在MST上。 

int n, m, ans[N];
bool v[M]; 
map<int, int> mp[N];

inline int getint() {
    char ch = getchar(); int x = 0; 
     while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
    return x;
}

struct pa {
    int t, a, b;
    pa() {}
    pa(int t, int a, int b) : t(t), a(a), b(b) {}
}q[N]; 

struct edge {
    int u, v, t;
    edge() {}
    edge(int u, int v, int t) : u(u), v(v), t(t) {}
    friend bool operator < (edge a, edge b) {
        return a.t < b.t;
    }
}e[M]; 

struct us {
    int fa[N], n;
    inline void set(int _n) {
        n = _n; for (int i=1; i<=n; ++i) fa[i] = i;
    }
    inline int getf(int x) {
        return fa[x] == x ? x : fa[x] = getf(fa[x]);
    }
    inline void un(int fx, int fy) {
        fa[fx] = fy;
    }
}U;
 
struct LCT {
    int ch[M][2], fa[M], val[M], mx[M], id[M];
    bool rev[M]; 
    inline void set() {
        memset(ch, 0, sizeof ch);
        memset(fa, 0, sizeof fa);
        memset(val, 0, sizeof val);
        memset(mx, 0, sizeof mx);
        memset(rev, 0, sizeof rev);
        memset(id, 0, sizeof id); 
    }
    # define ls ch[x][0]
    # define rs ch[x][1] 
    inline void up(int x) {
        if(!x) return ;
        mx[x] = val[x]; id[x] = x;
        if(mx[x] < mx[ls]) mx[x] = mx[ls], id[x] = id[ls];
        if(mx[x] < mx[rs]) mx[x] = mx[rs], id[x] = id[rs]; 
    }
    inline void pushrev(int x) {
        if(!x) return ; 
        swap(ls, rs); 
        rev[x] ^= 1;
    }
    inline void down(int x) {
        if(!x || !rev[x]) return ;
        pushrev(ls), pushrev(rs);
        rev[x] = 0;
    }
    # undef ls
    # undef rs
    inline bool isrt(int x) {
        return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
    }
    inline void rotate(int x) {
        int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1; 
        if(!isrt(y)) ch[z][ch[z][1] == y] = x;
        fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z;
        ch[y][ls] = ch[x][rs]; ch[x][rs] = y;
        up(y); up(x);
    }
    int st[M]; 
    inline void splay(int x) {
        int stn = 0, tx = x;
        while(!isrt(tx)) st[++stn] = tx, tx = fa[tx];
        st[++stn] = tx;
        for (int i=stn; i; --i) down(st[i]);
        while(!isrt(x)) {
            int y = fa[x], z = fa[y];
            if(!isrt(y)) {
                if((ch[y][0] == x) ^ (ch[z][0] == y)) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    inline int access(int x) {
        int t = 0;
        for (; x; t = x, x = fa[x]) {
            splay(x); 
            ch[x][1] = t;
            up(x);
        }
        return t;
    }
    inline void makeroot(int x) {
        access(x); splay(x); pushrev(x);
    }
    inline void link(int x, int y) {
        makeroot(x); fa[x] = y;
    } 
    inline int cut(int x, int y) {
        makeroot(x); access(y); splay(y); ch[y][0] = fa[x] = 0; up(y); 
    }
    inline int split(int x, int y) {
        makeroot(x); access(y); splay(y); return y;
    }
}T;

int main() {
    n = getint(), m = getint();
    int Q = getint(); U.set(n); T.set(); 
    for (int i=1; i<=m; ++i) e[i].u = getint(), e[i].v = getint(), e[i].t = getint();
    sort(e+1, e+m+1); 
    for (int i=1; i<=m; ++i) mp[e[i].u][e[i].v] = i, mp[e[i].v][e[i].u] = i; 
    for (int i=1; i<=Q; ++i) { 
         q[i].t = getint(); q[i].a = getint(), q[i].b = getint();
        if(q[i].t == 2) v[mp[q[i].a][q[i].b]] = 1; 
    }
    for (int i=1, x; i<=m; ++i) {
        if(v[i]) continue; 
        int fu = U.getf(e[i].u), fv = U.getf(e[i].v);
        if(fu != fv) { 
            x = i+n;
            U.un(fu, fv);
            T.val[x] = e[i].t;
            T.link(e[i].u, x);
            T.link(e[i].v, x);
        }
    }
    for (int i=Q, x, t, y; i; --i) {
        x = T.split(q[i].a, q[i].b); 
        if(q[i].t == 1) ans[i] = T.mx[x];
        else {
            // adde (q[i].a, q[i].b)
            y = n + mp[q[i].a][q[i].b];
            t = e[y-n].t;
            if(t < T.mx[x]) { 
                T.val[y] = t; t = T.id[x];
                T.cut(t, e[t-n].u);    
                T.cut(t, e[t-n].v); 
                T.link(q[i].a, y);
                T.link(q[i].b, y);
            }
        }
    }
    for (int i=1; i<=Q; ++i) if(q[i].t == 1) printf("%d\n", ans[i]); 
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/galaxies/p/bzoj2594.html

你可能感兴趣的:(bzoj2594 [Wc2006]水管局长数据加强版)