【奇偶传递 扩展域】 奇偶游戏

传送门

题意

给定一个\(N\)表示一个\(01\)序列\(S\)的长度,给定\(M\)个指示,每个指示一个\(l、r\),以及说明关系的字符串

  • \((l,r,odd)\),表示\((l,r)\)有偶数个\(1\)
  • \((l,r,even)\),表示\((l,r)\)有奇数个\(1\)

求出在多少个指示后出现矛盾

数据范围

\(N \leq 10^{9}, M \leq 10000\)

题解

将每个给定的都看作是条件,同样用到前缀和,\(x\)表示\(l-1\)\(y\)表示 \(r\)

  • 如果有偶数个,合并\(x_{odd}\)\(y_{odd}\)\(x_{even}\)\(y_{even}\),说明\(x\)为奇数和\(y\)为奇数可以互相推出,\(x\)为偶和\(y\)为偶也可以互相推出。

  • 如果有奇数个,那么合并\(x_{odd}\)\(y_{even}\)\(x_{even}\)\(y_{odd}\),说明\(x\)为奇数和\(y\)为偶数可以互相推出,\(x\)为偶和\(y\)为奇也可以互相推出。

相当于在无向图中维护连通性关系,满足传递性,\(l\)的奇数域即离散化后的自身,偶数域表示为将\(l+N\)后离散化的值,\(r\)同理

  • 因为一次性合并两个域名,所以只需要判断其中一个即可

    • \(l\)\(r\)的奇偶性不同时,如果\(x_{odd} = y_{odd}\)\(x_{even} =y_{even}\) 即矛盾

    • 当奇偶性相同时,如果\(x_{odd} = y_{even}\)\(x_{even}=y_{odd}\)时矛盾

Code

#include<bits/stdc++.h>
using namespace std;

#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)

const int N=1e5+10;


int fa[N*2];
int n,m,cnt;
unordered_map<int,int> rec;

int find(int x)
{
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}

void merge(int a,int b)
{
    int pa=find(a),pb=find(b);
    if(pa!=pb)
    {
        fa[pa]=pb;
    }
}
int disperse(int x)
{
    if(!rec[x]) rec[x]=++cnt;
    return rec[x];
}
int main()
{
    cin>>n>>m;
    rep(i,0,N*2+1) fa[i]=i;
    char op[5];int l,r;
    int diff;

    rep(i,1,m+1)
    {
        cin>>l>>r>>op;
        l=disperse(l-1),r=disperse(r);
        int lodd=l,leven=disperse(l+n),rodd=r,reven=disperse(r+n);
        if(op[0]=='e') diff=0;
        else diff=1;
        if(diff)
        {
            if(find(lodd) == find(rodd))
            {
                cout<<i-1<<endl;
                return 0;
            }
            merge(lodd,reven);merge(leven,rodd);
        }
        else 
        {
            if(find(lodd)==find(reven))
            {
                cout<<i-1<<endl;
                return 0;
            }
            merge(lodd,rodd);merge(leven,reven);
        }
    }
    cout<<m<<endl;
}
posted @ 2020-09-30 22:50  Hyx'  阅读(215)  评论(0编辑  收藏  举报