zoukankan      html  css  js  c++  java
  • BZOJ2303 APIO2011方格染色

    这题太神了

    首先我们可以发现只有当i和j都是偶数时a[1][1]^a[1][j]^a[i][1]^a[i][j]=1才满足情况,其它时都为0

    所以我们可以先把i和j都为偶数的地方^1变为0

    下面才是最牛逼的地方,并查集的应用在这里体现的淋漓尽致。

    0表示相同 1表示不同

    一开始赋初值都表示为相同

    然后每次更新并查集时只要更新他到根所有的数异或起来就是他与根的关系

    由于根的g一定为0,所以此时得到的还有它实际应该是多少

    我们假设一种比较复杂的情况

    我们只有a[1][j]^a[i][1]^a[i][j]=0才成立!

    假设此时a[i][j]的值为1(题目给出)

    所以当且仅当a[1][j]与a[i][1]颜色不同时才成立

    假设此时i到根异或起来为1,j到根异或起来为0

    也就是说i与根颜色不同,j与根颜色相同

    那么我们把两根合并时两根关系应该是什么?

    相同对不对!

    我们又发现此时分于两树时a[1][j]^a[i][1]^a[i][j]也为0(1^0^1=0)

    结果一样对不对!

    仔细想想其实他是因为异或满足的三角关系

    于是乎很轻松的解决了

    By:大奕哥

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=2e6+5,mod=1e9;
     4 typedef long long ll;
     5 struct node{
     6     int x,y,z;
     7 }a[N];
     8 int n,m,k,fa[N],g[N];
     9 int get(int x)
    10 {
    11     if(x==fa[x])return x;
    12     int t=get(fa[x]);
    13     g[x]^=g[fa[x]];
    14     return fa[x]=t;
    15 }
    16 ll calc()
    17 {
    18     for(int i=1;i<=m+n;++i)fa[i]=i=i,g[i]=0;
    19     fa[1+n]=1;
    20     for(int i=1;i<=k;++i)
    21     {
    22         int fx=get(a[i].x),fy=get(a[i].y+n);
    23         int tmp=g[a[i].x]^g[a[i].y+n]^a[i].z;
    24         if(fx!=fy){
    25             g[fx]=tmp;fa[fx]=fy;
    26         }
    27         else if(tmp)return 0;
    28     }
    29     int ans=0;
    30     for(int i=1;i<=n+m;++i)
    31     {
    32         if(get(i)==i)
    33         {
    34             if(ans==0)ans=1;
    35             else
    36             {
    37                 ans<<=1;ans%=mod;
    38             }
    39         }
    40     }
    41     return ans;
    42 }
    43 int main()
    44 {
    45     scanf("%d%d%d",&n,&m,&k);
    46     int flag=-1;
    47     for(int i=1;i<=k;++i)
    48     {
    49         scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    50         if(a[i].x+a[i].y==2){flag=a[i].z,k--,i--;continue;}
    51         if(!((a[i].x|a[i].y)&1))a[i].z^=1;
    52     }
    53     ll ans=0;
    54     if(flag==-1||flag==0)ans=calc();
    55     if(flag==-1||flag==1){
    56         for(int i=1;i<=k;++i)
    57         if(a[i].x>1&&a[i].y>1)
    58         a[i].z^=1;
    59         ans+=calc();
    60     }
    61     ans%=mod;
    62     printf("%lld
    ",ans);
    63     return 0;
    64 }
  • 相关阅读:
    poj3693 Maximum repetition substring (后缀数组+rmq)
    spoj687 REPEATS
    bzoj3626: [LNOI2014]LCA (树链剖分+离线线段树)
    bzoj2243 [SDOI2011]染色 (树链剖分+线段树)
    SPOJ QTREE- Query on a tree (树链剖分)
    hdu5662 YJQQQAQ and the function (单调栈)
    hdu4348 To the moon (主席树 || 离线线段树)
    hdu3565 Bi-peak Number (有上界和下界的数位dp)
    修改文件上传大小限制
    强制不按行
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8403492.html
Copyright © 2011-2022 走看看