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

 

posted @ 2017-08-04 11:15  19992147  阅读(141)  评论(0编辑  收藏  举报