CF461D Complicated Task

2.5寒假训练 Complicated Task (Standard IO)
Time Limits: 1000 ms Memory Limits: 262144 KB
Description
Description
Input
Input
Output
Output
Sample Input

3 2
1 1 x
2 2 o

Sample Output

2

Data Constraint
对于30%的数据,N<=15
对于100%的数据,N,K<=10^5


解题思路

已知了第一行,就能知道整幅图的样子了:
假设第i行j个为 f[i][j] 那么为了满足 (i1,j) 满足条件,有

f[i][j]f[i1][j1]f[i1][j+1]f[i2][j]=0
也就是
f[i][j]=f[i1][j1]f[i1][j+1]f[i2][j]

观察图与第一行的关系:
Analysis
像这样黑白格分块,每一个黑格都对应着第一行某连续子黑格的异或,算出构成格子 (x,y) 的异或区间为 (1,(max{xy,yx}1,min{2nxy+1,x+y1}])
想到 i(l,r]a[x]=S[l]S[r] (其中 S[x]=i[0,x]a[x]
(x,y) 已知时,令 l=max{xy,yx}1,r=min{2nxy+1,x+y1}
a(x,y)=1(o) S[l]S[r]=1 S[l]S[r]
同理若 a(x,y)=0(x) S[l]=S[r] 知道了所有 S[] 通过异或可以知道第一行,进而知道整个矩阵。

问题转化成了给出相等与不相等的限制,输出方案数,并查集维护。
将每个点分裂成两个x0,x1
l0与r0、l1与r1连通表示S[l]=S[r]
l1与r0、r1与l0连通表示S[l]≠S[r]
若限制矛盾,输出0,
答案一定为 2k k为不在非含0联通块的联通块个数(S[0]=0)

#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100100
#define mo 1000000007

using namespace std;

int fa[N+N],k,n;
bool p=1;

int get(int x){return x==fa[x]?x:(fa[x]=get(fa[x]));}
void mersame(int x,int y){
    int a0=get(x+x-1),a1=get(x+x),b0=get(y+y-1),b1=get(y+y);
    if(a0==b1 || a1==b0)p=0;else fa[b0]=a0,fa[b1]=a1;
}
void merdiff(int x,int y){
    int a0=get(x+x-1),a1=get(x+x),b0=get(y+y-1),b1=get(y+y);
    if(a0==b0 || a1==b1)p=0;else fa[b1]=a0,fa[b0]=a1;
}

int main(){
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n+n+4;i++)fa[i]=i;
    for(int i=1;i<=k;i++){
        int x,y;scanf("%d %d ",&x,&y);char c=getchar();
        int h=max(x-y,y-x)+1,t=min(2*n-x-y+1,x+y-1)+2;
        if(c=='o')merdiff(h,t);else mersame(h,t);
        if(!p)break;
    }
    if(p){
        int ans=1;
        for(int i=1;i<=n+n+4;i++)get(i);
        for(int i=5;i<=n+n+4;i+=2)
            if(fa[i]==i && i!=fa[1] && i!=fa[2] && i!=fa[3] && i!=fa[4])ans=ans*2%mo;
        printf("%d",ans);
    }else printf("0");
}

猜你喜欢

转载自blog.csdn.net/white_elephant/article/details/79266591