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\n",tr[1].ans[1],tr[1].ans[0]);
74 }

原文地址:https://www.cnblogs.com/yyc-jack-0920/p/8419622.html

时间: 2024-07-28 19:55:40

bzoj 1453 双面棋盘的相关文章

bzoj 1453: [Wc]Dface双面棋盘

1453: [Wc]Dface双面棋盘 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 617  Solved: 317[Submit][Status][Discuss] Description Input Output Sample Input Sample Output HINT 用线段树+数组模拟并查集,维护每一列的连通性,然后暴力合并就行了,常数巨大 #include<cstdio> #include<cstring> #inc

1453: [Wc]Dface双面棋盘 (线段树+并茶几)

Description Input Output Sample Input Sample Output HINT 1 /* 2 线段树+并查集维护 3 线段树维护每列的信息 4 le 代表区间左端一列连通性的信息 5 ri 代表区间右端一列连通性的信息 6 w,b 分别代表白色连通块和黑色连通块的个数 7 lb 代表区间左端一列黑白点的信息 8 rb 代表区间右端一列黑白点的信息 9 tmp用来暂时存储连通块个数 10 */ 11 #include<cstdio> 12 #include<

BZOJ 1057: [ZJOI2007]棋盘制作 悬线法求最大子矩阵+dp

1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减

BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define b(x) (1 <&l

BZOJ 1057: [ZJOI2007]棋盘制作( dp + 悬线法 )

对于第一问, 简单的dp. f(i, j)表示以(i, j)为左上角的最大正方形, f(i, j) = min( f(i + 1, j), f(i, j + 1), f(i + 1, j + 1)) + 1 (假如(i, j)和右边和下边不冲突) 第二问就是经典的悬线法解决最大子矩阵了, 维护悬线H[i][j], 左边右边延伸的最长距离.先一行一行求出这一行的L, R, 然后再从上往下扫, 维护H, L, R 写完我才发现我脑残了...最大的正方形一定是在最大子矩阵里面啊...所以其实不用dp.

bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link

2706: [SDOI2012]棋盘覆盖 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 255  Solved: 77[Submit][Status] Description 在一个N*M个方格组成的棋盘内,有K个方格被称为特殊方格.我们要使用一组俄罗斯方块来覆盖这个棋盘,保证特殊方格不能被覆盖,非特殊方格只能被一个俄罗斯方块覆盖,求最多能容纳的俄罗斯方块的数量. 已知有以下三组俄罗斯方块,一个棋盘可能用其中的某一组. Input 第一行三个整数

BZOJ 1057: [ZJOI2007]棋盘制作

Decsription 给你一个矩阵,求最大了 01相间 的矩阵. Sol DP+悬线法. 这是一个论文啊 <浅谈用极大化思想解决最大子矩形问题>--王知昆. 枚举每一根悬线,记录最左/右/上能到达的点,统计答案. Code /************************************************************** Problem: 1057 User: BeiYu Language: C++ Result: Accepted Time:1384 ms Me

bzoj1453: [Wc]Dface双面棋盘

Description Input Output 经典的按时间分治维护图的动态连通性 #include<cstdio> #include<vector> int n,m,ans[2]; int v[207][207],id[207][207],idp=0,t1[207][207],t2[207][207]; int f[40007],h[40007],aa[40007][2]; int*op1[1000007],op2[1000007],opp=0; inline void set

BZOJ 1057 ZJOI2007 棋盘制作 单调栈

题目大意:给定一个黑白两色的矩阵,求最大的黑白相间的子正方形和子矩阵 将奇数位置的点反色,然后就是求纯色的最大子正方形和子矩阵 将矩阵一层层剖分,每层上方是一段类似于▆▃▇▂▉的东西,用单调栈跑出每个点向左向右能拓展到的最大距离,更新答案即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 2020 using namespace