Timus 1003. Parity 【并查集】

传送门


输入的询问可能=0
巨坑…..因此re一晚上


sum[j]=ji=0a[i]   (mod2)
sum[a]=sum[b]sum[b]=sum[c]sum[a]=sum[b]=sum[c]
便2,sum[x]=1sum[y]=0

[i,j],sum[j]sum[i1]=0  (mod 2)
find(i1)==find(j)

[i,j],sum[j]sum[i1]=1  (mod 2)
maxVal=n
sum[x+maxVal]!=sum[x]
[i,j],ji1+maxVali1,j

#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))

using namespace std;

const int inf = 1e9+7;
const int N = 5e3 + 50;
const int M = 10*N+50;

char str[10];

struct data{
    int s,t;
    bool odd;
}ask[N];

int discr(int n){//离散化 返回最大值
    map<int,int>mp;
    for(int i=0;i<n;++i){
        mp[ask[i].s]=0;
        mp[ask[i].t]=0;
        mp[ask[i].s-1]=0;
    }
    int j=1;
    for(map<int,int>::iterator it=mp.begin();it!=mp.end();++it){
        it->second=j++;
    }
    for(int i=0;i<n;++i){
        ask[i].s=mp[ask[i].s];
        ask[i].t=mp[ask[i].t];
    }
    return mp.empty()?1:mp.rbegin()->second;//若不判空集,询问为0时re
}

struct Union{//并查集
    int par[M];
    void init(int n){
        for(int i=0;i<n;++i){
            par[i]=i;
        }
    }
    int find(int x){
        return x==par[x]?x:(par[x]=find(par[x]));
    }
    void merge(int x,int y){
        x=find(x);
        y=find(y);
        par[y]=x;
    }
}un;

int slove(int n){
    int maxVal=discr(n);
    un.init(2*maxVal+1);
    int ans=0;//可能询问为0,初始ans=0
    for(int i=0;i<n;++i){
        int x=ask[i].s-1;
        int y=ask[i].t;
        if(ask[i].odd){
            if(un.find(x)==un.find(y)){
                break;
            }
            else{
                un.merge(x+maxVal,y);
                un.merge(y+maxVal,x);
            }
        }
        else{
            if(un.find(x+maxVal)==un.find(y)){
                break;
            }
            else{
                un.merge(x,y);
                un.merge(x+maxVal,y+maxVal);
            }
        }
        ans=i+1;
    }
    return ans;
}

int main(){
    //freopen("/home/lu/code/r.txt","r",stdin);
    //freopen("/home/lu/code/w.txt","w",stdout);
    int n,k;
    while(~scanf("%d",&k)&&k!=-1){
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            scanf("%d%d%s",&ask[i].s,&ask[i].t,str);
            ask[i].odd=(str[0]=='o');
        }
        printf("%d\n",slove(n));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值