zoukankan      html  css  js  c++  java
  • bzoj 1453 双面棋盘

    题目大意:

    一个黑白方格图 

    支持单点修改 查询黑色与白色联通快个数

    思路:

    可以把每一行压为一个点

    使用线段树来维护

    然后两行合并的时候使用并查集来合并

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #define ll long long
    11 #define inf 2139062143
    12 #define MAXN 220
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    19     return x*f;
    20 }
    21 int n,g[MAXN][MAXN],f[MAXN<<2],t[MAXN<<2];
    22 int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    23 struct data {int ans[2],m[MAXN<<1];}tr[MAXN<<2];
    24 void solve(int k,int p)
    25 {
    26     tr[k].ans[g[p][1]]=1,tr[k].ans[g[p][1]^1]=0,tr[k].m[1]=tr[k].m[1+n]=1;
    27     for(int i=2,j=1;i<=n;i++)
    28     {
    29         if(g[p][i]!=g[p][j]) tr[k].ans[g[p][i]]++,j=i;
    30         tr[k].m[i]=tr[k].m[i+n]=j;
    31     }
    32 }
    33 void upd(int k,int p)
    34 {
    35     tr[k].ans[0]=tr[k<<1].ans[0]+tr[k<<1|1].ans[0];
    36     tr[k].ans[1]=tr[k<<1].ans[1]+tr[k<<1|1].ans[1];
    37     //cout<<k<<" "<<p<<endl;
    38     for(int i=1;i<=n*2;i++) f[i]=tr[k<<1].m[i];
    39     //for(int i=1;i<=n*2;i++) cout<<i<<" "<<f[i]<<" "<<tr[k<<1].m[i]<<endl;
    40     for(int i=1;i<=n*2;i++) f[i+n*2]=tr[k<<1|1].m[i]+n*2;
    41     //cout<<f[1]<<" "<<f[2]<<endl;
    42     for(int i=1;i<=n;i++) if(g[p][i]==g[p+1][i]&&find(i+n)!=find(i+n*2))tr[k].ans[g[p][i]]--,f[f[i+n]]=f[i+n*2];
    43     for(int i=1;i<=n*4;i++)
    44     {
    45         f[i]=find(i);
    46         if(i>n*3) t[f[i]]=i-n*2;
    47     }
    48     for(int i=1;i<=n;i++) tr[k].m[i]=i;
    49     for(int i=1;i<=n;i++) tr[k].m[i+n]=t[f[i+n*3]];
    50 }
    51 void build(int k,int l,int r)
    52 {
    53     if(l==r) {solve(k,l);return;}
    54     int mid=(l+r)>>1;
    55     build(k<<1,l,mid),build(k<<1|1,mid+1,r);
    56     upd(k,mid);
    57 }
    58 void mdf(int k,int l,int r,int x)
    59 {
    60     if(l==r) {solve(k,l);return;}
    61     int mid=(l+r)>>1;
    62     if(x<=mid) mdf(k<<1,l,mid,x);
    63     else mdf(k<<1|1,mid+1,r,x);
    64     upd(k,mid);
    65 }
    66 int main()
    67 {
    68     n=read();int a,b;
    69     for(int i=1;i<=n;i++)
    70         for(int j=1;j<=n;j++) g[i][j]=read();
    71     build(1,1,n);
    72     int T=read();
    73     while(T--) a=read(),b=read(),g[a][b]^=1,mdf(1,1,n,a),printf("%d %d
    ",tr[1].ans[1],tr[1].ans[0]);
    74 }
    View Code
  • 相关阅读:
    [pyqt4]mark
    EPC摘抄
    sockaddr struct 类型重定义
    linux编译警告 will be initialized after
    cout如何输出十六进制
    strcpy unsigned char
    c语言格式控制符
    c++字节数组转换为整型
    C++如何判断大小端
    C++中关于位域的概念
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8419622.html
Copyright © 2011-2022 走看看