zoukankan      html  css  js  c++  java
  • bzoj4025

    线段树分治+并查集

    跟1018很像,但是这里是带权并查集,修改时要注意,因为可回溯并查集不能路径压缩,所以也不能对保存到根路径长度的数组修改,每次连接,我们只对根的距离数组修改,这样不会影响操作结果,因为路径压缩就是把我们要求的d数组在find时把整个路径上的d数组都顺便修改了,这里我们用到哪个就求哪个,所以不会影响结果,

    d[b]=d[u]^d[v]^1

    所以b的值就应该是d[u]^d[v]^1,d是到跟路径长度的奇偶性,每次du^=d[u]其实就是查询两点之间的路径长度奇偶性

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 200010;
    struct dsu {
        int a, b, fa, sizea, sizeb, da, db;
        vector<int> dd;
        dsu(int a = 0, int b = 0, int fa = 0, int sizea = 0, int sizeb = 0, int da = 0, int db = 0) : a(a), b(b), fa(fa), sizea(sizea), sizeb(sizeb) {}
    } st[N];
    int n, m, top, T;
    int d[N], fa[N], size[N];
    vector<pair<int, int> > tree[N << 2];
    bool unite(pair<int, int> o)
    {
        int u = o.first, v = o.second, du = 0, dv = 0;
        while(fa[u] != u)
        {
            du ^= d[u];
            u = fa[u];
        }
        while(fa[v] != v)
        {
            dv ^= d[v];
            v = fa[v];
        }
        if(size[u] < size[v]) swap(u, v);
        st[++top] = dsu(u, v, fa[v], size[u], size[v], d[u], d[v]);
        if(u == v)
        {
            if(du == dv) return false;
            return true;
        }
        size[u] += size[v];
        d[v] = du ^ dv ^ 1;
        fa[v] = u;
        return true;
    }
    void del(int now)
    {
        while(top != now)
        {
            dsu x = st[top];
            size[x.a] = x.sizea;
            size[x.b] = x.sizeb;
            d[x.a] = x.da;
            d[x.b] = x.db;
            fa[x.b] = x.fa;
            --top;
        }
    }
    void dfs(int l, int r, int x, bool flag)
    {
        int now = top;
        for(int i = 0; i < tree[x].size(); ++i) if(!unite(tree[x][i])) flag = false;
        if(l == r)
        {
            if(flag) puts("Yes");
            else puts("No");
            del(now);
            return;
        }
        int mid = (l + r) >> 1;
        dfs(l, mid, x << 1, flag);
        dfs(mid + 1, r, x << 1 | 1, flag);
        del(now);
    }
    void update(int l, int r, int x, int a, int b, pair<int, int> o)
    {
        if(l > b || r < a) return;
        if(l >= a && r <= b) 
        {
            tree[x].push_back(o);
            return;
        }
        int mid = (l + r) >> 1;
        update(l, mid, x << 1, a, b, o);
        update(mid + 1, r, x << 1 | 1, a, b, o);
    }
    int main()
    {
        scanf("%d%d%d", &n, &m, &T);
        for(int i = 1; i <= n; ++i)
        {
            fa[i] = i;
            size[i] = 1;
        }
        for(int i = 1; i <= m; ++i)
        {
            int u, v, s, t;
            scanf("%d%d%d%d", &u, &v, &s, &t);
            update(1, T, 1, s + 1, t, make_pair(u, v));
        }
        dfs(1, T, 1, true);
        return 0;
    }
    View Code
  • 相关阅读:
    剑指Offer——数组中重复的数字
    基于Google Protobuff和Mina的RPC
    Google Protocol Buffers 编码(Encoding)
    Protocol Buffers 语法指南
    Google Protocol Buffers 入门
    Google Protocol Buffers 概述 转
    Protobuf语言指南
    基于Protobuf的通讯库--Poppy简介
    log4cxx第三篇----使用多个logger
    log4CXX第二篇---配置文件(properties文件)详解
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7284008.html
Copyright © 2011-2022 走看看