poj - 1733 种类并查集+离散化

题意:有一个长度已知的01串,给出[l,r]这个区间中的1是奇数个还是偶数个,给出一系列语句问前几个是正确的

一类经典的并查集题目,经典模型就是将[l,r]这个区间化为(l-1,r],那么1的个数就可以表示为sum[r]-sum[l-1],也就确定了奇偶性,我们可以用r[]数组表示这个端点到它的根节点的1的奇偶(这个区间就是(i,root(i)](0代表偶,1代表奇)  对于每个输入的区间,我们查找它们的根节点是否相同。

1.如果相同,证明这个区间的奇偶性在之前已经得知,那么直接判断即可。

2.如果不同,那么就是u-1与v此时不在同一个集合中,那么我们可以知道(u-1,root([u-1])]区间和(v,root([v])]区间1的奇偶,并且我们知道了(u-1,v]区间1的奇偶,那么就可以推算出(root([u-1]),root([v])]区间的属性,进而合并两者。在合并时,根节点,r[root(u)]=r(u)^r(v)^r(u-1,v], 在路径压缩过程中r[i]=r[i]^r[root(i)],比如(a,b]中1的个数为偶数,(b,c]中1的个数为奇数,(a,c]中1的个数显然为奇数

数据范围1e9,很大,语句5000条,所以需要把数据离散化

学习了一下离散化https://blog.csdn.net/xiangaccepted/article/details/73276826

const int maxn=1e5+10;

int a[maxn], t[maxn];

int n;

scanf("%d",&n);

for(int i=1;i<=n;i++)

scanf("%d",a[i]),t[i]=a[i];

    sort(t+1,t+n+1);

    m=unique(t+1,t+1+n)-t-1;//m为不重复的元素的个数

for(int i=1;i<=n;i++)

a[i]=lower_bound(t+1,t+1+m,a[i])-t;

//原来的a[i]离散化后成了后来的a[i];

//离散化后的a[i]范围是(1-m);

链接:poj 1733

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include <cmath>
#include <map>
#include <stack>
using namespace std;

const int maxn = 10000 + 10;
const int inf = 0x3f3f3f3f;

int n, m;
int father[maxn];
int r[maxn];
int que[maxn];
int cnt;

struct node {
    int u, v;
    int res;
}a[maxn];

int getf(int x) {
    if(x != father[x]) {
        int t = father[x];
        father[x] = getf(father[x]);
        r[x] = r[x] ^ r[t];
    }
    return father[x];
}

int main()
{
    int T;
    while(cin >> n) {
        cin >> m;
        char str[10];
        cnt = 0;
        for(int i = 0; i < m; i++) {
            scanf("%d %d %s", &a[i].u, &a[i].v, str);
            a[i].u--;
            if(str[0] == 'e') {
                a[i].res = 1;
            }
            else {
                a[i].res = 0;
            }
            que[cnt++] = a[i].u;
            que[cnt++] = a[i].v;
        }
        sort(que, que + cnt);
        int ans = unique(que, que + cnt) - que;
        for(int i = 0; i < ans; i++) {
            father[i] = i;
            r[i] = 0;
        }
        int sum = 0;
        for(int i = 0; i < m; i++) {
            int u = lower_bound(que, que + ans, a[i].u) - que;
            int v = lower_bound(que, que + ans, a[i].v) - que;
            int ra = getf(u);
            int rb = getf(v);
            if(ra == rb) {
                if(r[u] == r[v] && a[i].res == 0) {
                    break;
                }
                if(r[u] != r[v] && a[i].res == 1) {
                    break;
                }
                sum++;
            }
            else {
                if(a[i].res == 0) {
                    father[ra] = rb;
                    r[ra] = r[u] ^ r[v] ^ 1;
                }
                else {
                    father[ra] = rb;
                    r[ra] = r[u] ^ r[v];
                }
                sum++;
            }
        }
        cout << sum << endl;
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/C_CQQ/article/details/80033204