zoukankan      html  css  js  c++  java
  • JZOJ 6860. 【2020.11.14提高组模拟】鬼渊传说(前缀和+指针)

    JZOJ 6860. 【2020.11.14提高组模拟】鬼渊传说

    题解

    • 这题要用到图论中的欧拉定理,即 V − E + F = 2 V-E+F=2 VE+F=2,其中 V V V为点数, E E E为边数, F F F为面数(包括整个图形以外的部分),可以用归纳法证明,对任意连通平面图成立。
    • 那么在这题里把黑格看成点,可以通过判断欧拉定理是否成立来判断是否只有一个连通块。
    • 设四元环(相邻的四格构成的正方形)个数为 S S S,显而易见 F = S + 1 F=S+1 F=S+1,因为网格图中的面只能是四元环(除了整个图形以外的部分),则有 V − E + S = 1 V-E+S=1 VE+S=1
    • 可以分别预处理好点、横向边、纵向边、四元环个数前缀和, V − E + S V-E+S VE+S的值可以用前缀和计算得出。注意不同的前缀和式子略有不同,所有需要把横向边和纵向边拆开算。
    • 先忽略中间的空腔,可以先枚举上下边界,然后枚举右边界时,计算出左边界的前缀和值应为多少,用桶维护,在桶里查找对应的值加入答案。
    • 接着把空腔考虑进来,可以先BFS一遍求出所有空腔的上下左右边界 x 0 , x 1 , y 0 , y 1 x0,x1,y0,y1 x0,x1,y0,y1
    • 后面的计算过程中,枚举每个上边界 i i i时, 把所有 x 0 > i x0>i x0>i的空腔记录到 y 1 y1 y1的位置,确定下边界后,可以从左往右扫一遍,依次求出每个 k k k作为右边界时, 左边界可到的最小值 d k d_k dk d k d_k dk是单调不下降的。
    • 最后从右往左枚举右边界,用指针 l , r l,r l,r记录可作为左边界的区间,然后不断移动指针修改桶里的值。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 310
    int a[N][N], f[N][N], g0[N][N], g1[N][N], h[N][N];
    int vi[N][N], fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    int last[N], nxt[N * N], to[N * N], li[N * N], len;
    int s[N * N], bz[N * N], p[N], d[N];
    int x0, x1, y0, y1, n, m;
    struct {
    	int x0, y0, x1, y1;
    }c[N * N];
    void dfs(int x, int y) {
    	x0 = min(x, x0), y0 = min(y, y0);
    	x1 = max(x, x1), y1 = max(y, y1);
    	vi[x][y] = 1;
    	for(int i = 0; i < 4; i++) {
    		int xx = x + fx[i][0], yy = y + fx[i][1];
    		if(xx < 1 || xx > n || yy < 1 || yy > m || vi[xx][yy] || a[xx][yy]) continue;
    		dfs(xx, yy);
    	}
    }
    void add(int x, int y, int z) {
    	to[++len] = y;
    	li[len] = z;
    	nxt[len] = last[x];
    	last[x] = len;
    }
    int main() {
    	int i, j, k, l, r;
    	char ch;
    	scanf("%d%d
    ", &n, &m);
    	for(i = 1; i <= n; i++) 
    	{
    		for(j = 1; j <= m; j++) scanf("%c", &ch), a[i][j] = ch - 48;
    		scanf("
    ");
    	}
    	int tot = 0;
    	for(i = 2; i < n; i++) {
    		for(j = 2; j < m; j++) if(!vi[i][j] && !a[i][j]) {
    			x0 = y0 = m + n;
    			x1 = y1 = -1;
    			dfs(i, j);
    			if(x0 == 1 || y0 == 1 || x1 == n || y1 == m) continue;
    			c[++tot] = {x0, y0, x1, y1};
    		}
    	}
    	for(i = 1; i <= n; i++) {
    		for(j = 1; j <= m; j++) {
    			f[i][j] = f[i][j - 1] + f[i - 1][j] - f[i - 1][j - 1] + (a[i][j] == 1);
    			g0[i][j] = g0[i][j - 1] + g0[i - 1][j] - g0[i - 1][j - 1] + (a[i][j - 1] && a[i][j]);
    			g1[i][j] = g1[i][j - 1] + g1[i - 1][j] - g1[i - 1][j - 1] + (a[i - 1][j] && a[i][j]);
    			h[i][j] = h[i][j - 1] + h[i - 1][j] - h[i - 1][j - 1] + (a[i][j] && a[i][j - 1] && a[i - 1][j] && a[i - 1][j - 1]);
    		}
    	}
    	int id = 0, ans = 0, t;
    	for(i = 1; i <= n; i++) {
    		len = 0;
    		memset(last, 0, sizeof(last));
    		for(j = 1; j <= tot; j++) if(i < c[j].x0) add(c[j].y1, c[j].x1, c[j].y0);
    		for(j = i; j <= n; j++) {
    			d[0] = 0;
    			for(k = 1; k <= m; k++) {
    				d[k] = d[k - 1];
    				for(l = last[k - 1]; l; l = nxt[l]) if(to[l] < j) d[k] = max(d[k], li[l] - 1);
    			}
    			id++;
    			for(k = 0; k <= m; k++)	p[k] = f[j][k] - f[i - 1][k] - g0[j][k + 1] + g0[i - 1][k + 1] - g1[j][k] + g1[i][k] + h[j][k + 1] - h[i][k + 1] + 1;
    			l = m, r = m - 1;
    			for(k = m; k; k--) {
    				t = f[j][k] - f[i - 1][k] - g0[j][k] + g0[i - 1][k] - g1[j][k] + g1[i][k] + h[j][k] - h[i][k];
    				while(l > d[k]) {
    					l--;
    					if(bz[p[l]] < id) bz[p[l]] = id, s[p[l]] = 0;
    					s[p[l]]++;
    				}
    				while(r >= k) s[p[r]]--, r--;
    				if(bz[t] == id) ans += s[t];
    			}
    		}
    	}
    	printf("%d", ans);
    	return 0;
    }
    
  • 相关阅读:
    【转】win8.1下安装ubuntu
    Codeforces 1025G Company Acquisitions (概率期望)
    Codeforces 997D Cycles in Product (点分治、DP计数)
    Codeforces 997E Good Subsegments (线段树)
    Codeforces 1188E Problem from Red Panda (计数)
    Codeforces 1284E New Year and Castle Building (计算几何)
    Codeforces 1322D Reality Show (DP)
    AtCoder AGC043C Giant Graph (图论、SG函数、FWT)
    Codeforces 1305F Kuroni and the Punishment (随机化)
    AtCoder AGC022E Median Replace (字符串、自动机、贪心、计数)
  • 原文地址:https://www.cnblogs.com/LZA119/p/14279485.html
Copyright © 2011-2022 走看看