日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ1453: [Wc]Dface双面棋盘

發(fā)布時間:2023/11/30 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ1453: [Wc]Dface双面棋盘 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 784 Solved: 422
[Submit][Status][Discuss]

Description

佳佳有一個 nnn 行 nnn 列的黑白棋盤,每個格子都有兩面,一面白色,一面黑色。佳佳把棋盤平放在桌子上,因此每個格子恰好一面朝上,如下圖所示:

QQ20180116200234.png

我們把每行從上到下編號為 111 ,222 ,333 ,……,nnn ,各列從左到右編號為 111 ,222 ,333 ,……,nnn ,則每個格子可以用棋盤坐標(biāo)(x,y)(x, y)(x,y) 表示。在上圖中,有 888 個格子黑色朝上,另外 171717 個格子白色朝上。

如果兩個同色格子有一條公共邊,我們稱這兩個同色格子屬于同一個連通塊。上圖共有 555 個黑色連通塊和 333 個白色連通塊。

佳佳可以每分鐘將一個格子翻轉(zhuǎn)(即白色變成黑色,黑色變成白色),然后計算當(dāng)前有多少個黑色連通塊和白色連通塊,你能算得更快嗎?

Input

輸入文件的第一行包含一個正整數(shù) nnn ,為格子的邊長。以下 nnn 行每行 nnn 個整數(shù),非 000 即 111 ,表示初始狀態(tài)。000 表示白色,111 表示黑色。下一行包含一個整數(shù) mmm ,表示操作的數(shù)目。以下 mmm 行每行兩個整數(shù) xxx , yyy (111 ≤ xxx , yyy ≤ nnn ),表示把坐標(biāo)為(x,y)(x, y)(x,y) 的格子翻轉(zhuǎn)。

Output

輸出文件包含 mmm 行,每行對應(yīng)一個操作。該行包括兩個整數(shù) bbb , www ,表示黑色區(qū)域和白色區(qū)域數(shù)目。
【約定】

○1 ≤ n ≤ 200

○1 ≤ m ≤ 10,000

Sample Input

5
0 1 0 0 0
0 1 1 1 0
1 0 0 0 1
0 0 1 0 0
1 0 0 0 0
2
3 2
2 3

Sample Output

4 3
5 2

HINT

翻轉(zhuǎn)(3,2)(3, 2)(3,2) 之后,棋盤變?yōu)?#xff1a;

QQ20180116200629.png

有 444 個黑色區(qū)域和 333 個白色區(qū)域

翻轉(zhuǎn)(2,3)(2, 3)(2,3) 之后,棋盤變?yōu)?#xff1a;

QQ20180116200639.png

有 555 個黑色區(qū)域和 222 個白色區(qū)域

Source

鳴謝劉汝佳先生授權(quán)使用

題解

用線段樹維護(hù)行,并查集合并
線段樹每個節(jié)點(diǎn)維護(hù)區(qū)間[l,r]中,行l(wèi)的并查集,行r的并查集,用于查詢l與r的聯(lián)通情況,維護(hù)[l,r]行的白色連通塊數(shù)和黑色連通塊數(shù)。維護(hù)并查集父節(jié)點(diǎn)個數(shù)。

合并即可。

注意,并查集維護(hù)的時候,其所指的父親不是這些格子自身,而是虛出來的節(jié)點(diǎn)。在兩個區(qū)間合并的時候,處理虛的節(jié)點(diǎn)的連通性,右區(qū)間虛節(jié)點(diǎn)編號要加上左區(qū)間虛的節(jié)點(diǎn)的個數(shù),合并后的虛節(jié)點(diǎn)繼承回區(qū)間的左右并查集即可。離散化一下,不然可能會很大。。

推薦題解

#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <map> #include <cmath> inline int max(int a, int b){return a > b ? a : b;} inline double max(double a, double b){return a - b > 0 ? a : b;} inline int min(int a, int b){return a < b ? a : b;} inline void swap(int &x, int &y){int tmp = x;x = y;y = tmp;} inline void read(int &x) {x = 0;char ch = getchar(), c = ch;while(ch < '0' || ch > '9') c = ch, ch = getchar();while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();if(c == '-') x = -x; } const int INF = 0x3f3f3f3f; const int MAXN = 200 + 10; int n, q, fa[MAXN << 2], g[MAXN][MAXN], vis[MAXN << 2]; int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]); } struct Node {int cnt, fal[MAXN << 1], far[MAXN << 1], wsize, bsize, l, r;Node(){cnt = wsize = bsize = l = r = 0, memset(fa, 0, sizeof(fa)), memset(far, 0, sizeof(far));} }node[MAXN << 2];void pushup(int o) {int l = o << 1, r = o << 1 | 1;if(node[l].cnt == 0){node[o] = node[r];return;}if(node[r].cnt == 0){node[o] = node[l];return;}for(int i = node[l].cnt + node[r].cnt;i;-- i) fa[i] = i, vis[i] = 0;node[o].wsize = node[l].wsize + node[r].wsize;node[o].bsize = node[l].bsize + node[r].bsize;for(int i = 1;i <= n;++ i)if(g[node[l].r][i] == g[node[r].l][i]){int f1 = find(node[l].far[i]), f2 = find(node[r].fal[i] + node[l].cnt);if(f1 != f2){fa[f1] = f2;if(g[node[l].r][i]) -- node[o].bsize;else -- node[o].wsize;}}node[o].cnt = 0;for(int i = 1;i <= n;++ i){int f1 = find(node[l].fal[i]), f2 = find(node[r].far[i] + node[l].cnt);if(!vis[f1]) vis[f1] = ++ node[o].cnt;if(!vis[f2]) vis[f2] = ++ node[o].cnt;node[o].fal[i] = vis[f1], node[o].far[i] = vis[f2];} } void calc(int o) {int wsize = 0, bsize = 0, pos = node[o].l, *fal = node[o].fal, *far = node[o].far;if(g[pos][1]) ++ bsize; else ++ wsize;fal[1] = far[1] = 1;for(int i = 2;i <= n;++ i){if(g[pos][i] != g[pos][i - 1])if(g[pos][i]) ++ bsize;else ++ wsize;fal[i] = far[i] = wsize + bsize;}node[o].cnt = wsize + bsize, node[o].wsize = wsize, node[o].bsize = bsize; } void build(int o = 1, int l = 1, int r = n) {node[o].l = l, node[o].r = r;if(l == r){calc(o);return;}int mid = (l + r) >> 1;build(o << 1, l, mid);build(o << 1 | 1, mid + 1, r);pushup(o); } void modify(int p, int o = 1, int l = 1, int r = n) {if(l == r){calc(o);return;}int mid = (l + r) >> 1;if(p <= mid) modify(p, o << 1, l, mid);else modify(p, o << 1 | 1, mid + 1, r);pushup(o); }int main() {read(n);for(register int i = 1;i <= n;++ i)for(register int j = 1;j <= n;++ j)read(g[i][j]);build();read(q);for(register int i = 1;i <= q;++ i){int tmp1, tmp2;read(tmp1), read(tmp2);g[tmp1][tmp2] ^= 1;modify(tmp1);printf("%d %d\n", node[1].bsize, node[1].wsize);}return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/huibixiaoxing/p/8599072.html

總結(jié)

以上是生活随笔為你收集整理的BZOJ1453: [Wc]Dface双面棋盘的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。