并查集对状态的维护

25 篇文章 0 订阅
24 篇文章 0 订阅

这里的题目一般都是维护状态,每个集合表示的是一种状态(一般为两个)

题目会询问第一次状态冲突的时候[并查集添加状态的时候发现已有状态并且状态不对]

数据结构K题

K题讲述的是:告诉你n个区间的和的奇偶,判断第一个矛盾的地方。

区间和的奇偶可以转换成可以维护的前缀和之差的奇偶,和为奇,前缀和sum[l-1]和sum[r]一定奇偶不同。

前者奇后者偶,或者反过来。这两种状态我们都添加到并查集里去。

那么怎么表示哪个是奇数呢,0~n为奇数,n+1~2*n+1为偶数。类似于罪犯分配问题。后者做过的前提我还没做出来K题,看到题解才恍然大悟,脑子不行就要靠刷题弥补。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;

const int MAXN = 1000050*2;

int n,m;
int f[MAXN];

struct UnionSet {
    UnionSet(int n) {
        for (int i = 0; i <= 2*n+1; i++) {
            f[i] = i;
        }
    }
    UnionSet(){}

    void uni(int x, int y) {
        f[find(x)] = find(y);
    }

    bool query(int x, int y) {
        return find(x) == find(y);
    }

    int find(int x) {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }

} us;

int main(){
    cin>>n>>m;
    char ch[10];
    us=UnionSet(n);
    FOR(i,1,m){
        int x,y;
        scanf("%d%d%s",&x,&y,ch);
        x--;
        if(ch[0]=='e'){
            if(us.query(x,y+n+1)||us.query(x+n+1,y)){
                cout<<i-1<<endl;
                return 0;
            }
            us.uni(x,y);
            us.uni(x+n+1,y+n+1);
        }
        else{
            if(us.query(x,y)||us.query(x+n+1,y+n+1)){
                cout<<i-1<<endl;
                return 0;
            }
            us.uni(x+n+1,y);
            us.uni(x,y+n+1);
        }
    }
    cout<<"ORZQHQH"<<endl;
}

罪犯分配问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值