Nanami's Digital Board CodeForces - 434B (棋盘dp)

大意: 给定01矩阵, m个操作, 操作1翻转一个点, 操作2求边界包含给定点的最大全1子矩阵

暴力枚举矩形高度, 双指针统计答案

#include <iostream>
#include <algorithm>
#include <math.h>
#include <cstdio>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <string.h>
#include <queue>
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;

const int N = 1e3+10, INF = 0x3f3f3f3f;
int n, m, q;
int a[N][N], U[N][N], D[N][N], L[N][N], R[N][N];

void init() {
	REP(i,1,n) REP(j,1,m) if (a[i][j]) {
		U[i][j]=U[i-1][j]+1;
		L[i][j]=L[i][j-1]+1;
	}
	PER(i,1,n) PER(j,1,m) if (a[i][j]) {
		D[i][j]=D[i+1][j]+1;
		R[i][j]=R[i][j+1]+1;
	}
}

void update(int x, int y) {
	a[x][y] ^= 1;
	REP(i,1,n) U[i][y]=(a[i][y]?U[i-1][y]+1:0);
	PER(i,1,n) D[i][y]=(a[i][y]?D[i+1][y]+1:0);
	REP(i,1,m) L[x][i]=(a[x][i]?L[x][i-1]+1:0);
	PER(i,1,m) R[x][i]=(a[x][i]?R[x][i+1]+1:0);
}

int query(int x, int y) {
	int ans = 0, t = U[x][y], l = y, r = y;
	PER(i,1,U[x][y]) {
		while (l>1&&U[x][l-1]>=i) --l;
		while (r<m&&U[x][r+1]>=i) ++r;
		if (U[x][l]>=i&&U[x][r]>=i) {
			ans = max(ans, i*(r-l+1));
		}
	}
	t = D[x][y], l = y, r = y;
	PER(i,1,D[x][y]) {
		while (l>1&&D[x][l-1]>=i) --l;
		while (r<m&&D[x][r+1]>=i) ++r;
		if (D[x][l]>=i&&D[x][r]>=i) {
			ans = max(ans, i*(r-l+1));
		}
	}
	t = L[x][y], l = x, r = x;
	PER(i,1,L[x][y]) {
		while (l>1&&L[l-1][y]>=i) --l;
		while (r<n&&L[r+1][y]>=i) ++r;
		if (L[l][y]>=i&&L[r][y]>=i) {
			ans = max(ans, i*(r-l+1));
		}
	}
	t = R[x][y], l = x, r = x;
	PER(i,1,R[x][y]) {
		while (l>1&&R[l-1][y]>=i) --l;
		while (r<n&&R[r+1][y]>=i) ++r;
		if (R[l][y]>=i&&R[r][y]>=i) {
			ans = max(ans, i*(r-l+1));
		}
	}
	return ans;
}

int main() {
	scanf("%d%d%d", &n, &m, &q);
	REP(i,1,n) REP(j,1,m) scanf("%d", &a[i][j]);
	init();
	REP(i,1,q) {
		int op, x, y;
		scanf("%d%d%d", &op, &x, &y);
		if (op==1) update(x,y);
		else printf("%d\n", query(x,y));
	}
}

Nanami's Digital Board CodeForces - 434B (棋盘dp)

原文地址:https://www.cnblogs.com/uid001/p/10436335.html

时间: 2024-10-09 10:20:21

Nanami's Digital Board CodeForces - 434B (棋盘dp)的相关文章

Codeforces Round #248 (Div. 1)——Nanami&#39;s Digital Board

题目连接 题意: 给n*m的0/1矩阵,q次操作,每次有两种:1)将x,y位置值翻转 2)计算以(x,y)为边界的矩形的面积最大值 (1?≤?n,?m,?q?≤?1000) 分析: 考虑以(x,y)为下边界的情况,h=(x,y)上边最多的连续1的个数.那么递减的枚举,对于当前hx,只需要看两侧能到达的最远距离,使得h(x,ty)不大于h即可.之后的枚举得到的两侧距离大于等于之前的,所以继续之前的两侧距离继续枚举即可. const int maxn = 1100; int n, m, q; int

codeforces248(div1) B Nanami&#39;s Digital Board

q次询问,每次询问可以对矩阵某一个值改变(0变1,1变0) 或者是查询子矩阵的最大面积,要求这个这个点在所求子矩阵的边界上,且子矩阵各店中全为1 用up[i][j]表示(i,j)这个点向上能走到的最长高度  若(i,j)为0 则up[i][j]值为0 同理,维护down,left, right数组 则每次查询时,从up[i][j]枚举至1作为子矩阵的高度,然后途中分别向左右扩展.若up[i][j - 1] >= up[i][j],则可向左扩展一个单位,答案为(r - l - 1) * 高度 同理

Codeforces Round #248 (Div. 1)——Nanami&amp;#39;s Digital Board

题目连接 题意: 给n*m的0/1矩阵,q次操作,每次有两种:1)将x,y位置值翻转 2)计算以(x,y)为边界的矩形的面积最大值 (1?≤?n,?m,?q?≤?1000) 分析: 考虑以(x,y)为下边界的情况,h=(x,y)上边最多的连续1的个数.那么递减的枚举,对于当前hx,仅仅须要看两側能到达的最远距离,使得h(x,ty)不大于h就可以.之后的枚举得到的两側距离大于等于之前的,所以继续之前的两側距离继续枚举就可以. const int maxn = 1100; int n, m, q;

Codeforces 13C Sequence --DP+离散化

题意:给出一个 n (1 <= n <= 5000)个数的序列 .每个操作可以把 n 个数中的某一个加1 或 减 1.问使这个序列变成非递减的操作数最少是多少 解法:定义dp[i][j]为将前i个数变为以j为结尾的非递减序列的最少操作次数. 则有: dp[i][j] = min(dp[i][j], min(dp[i][k]) + Cost(原来第i个位置上的数转换到j))  (1 <= k <= j) 即前i个数以j结尾的状态可以由前i-1个数以小于等于j的k结尾的状态转移过来,取

Codeforces 77C 树形dp + 贪心

题目链接:点击打开链接 题意: 给定n个点, 每个点的豆子数量 下面是一棵树 再给出起点 每走到一个点,就会把那个点的豆子吃掉一颗. 问:回到起点最多能吃掉多少颗豆子 思路:树形dp 对于当前节点u,先把子节点v都走一次. 然后再往返于(u,v) 之间,直到u点没有豆子或者v点没有豆子. dp[u] 表示u点的最大值.a[u] 是u点剩下的豆子数. #include <cstdio> #include <vector> #include <algorithm> #inc

炮(棋盘DP)

一直以为自己写的就是状态压缩,结果写完才知道是个棋盘dp 首先看一下题目 嗯,象棋 ,还是只有炮的象棋 对于方案数有几种,我第一个考虑是dfs,但是超时稳稳的,所以果断放弃 然后记得以前有过和这个题差不多的dp题 所以思路开始转向DP 经仔细思考后 将棋盘的状态压为三维 dp[i][k][j]; i:棋盘的第几行  k:前i行有几列放了一个炮棋  j:前i行有几列放了两个炮棋 因为炮会隔棋打,所以一列或者一行最多存在两个炮棋 所以 dp方程有6个元素: 1:不放炮棋,所以方程为 dp[i][k]

Codeforces 57C Array dp暴力找规律

题目链接:点击打开链接 先是计算非递增的方案, 若非递增的方案数为x, 则非递减的方案数也是x 答案就是 2*x - n 只需求得x即可. 可以先写个n3的dp,然后发现规律是 C(n-1, 2*n-1) 然后套个逆元即可. #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll long long #def

Codeforces 413D 2048(dp)

题目连接:Codeforces 413D 2048 题目大意:2048的游戏,两个相同的数x可以变成一个2*x,先给出n,表示在一个1*n的矩阵上面玩2048,规定每次向左移动,并且每次出现一个,给出序列n,表示出现的块的值,0表示既可以是2也可以是4,问说有多少种可能,使得游戏结束后的最大块的值大于等于2^k. 解题思路:dp[i][j][x]表示第i个位置,值为j,x表示先前有没有出现过大于2^k的数: 这种递增的情况可以直接表示为14(总和,以为后面的2,4如果变大,就肯定能和8想合在一起

Codeforces 455A Boredom (dp)

很裸的dp 状态转移方程 dp[i]=max(dp[i-1],dp[i-2]+dp[i]*i) #include<bits/stdc++.h> using namespace std; long long dp[100020]; int main() { int n,a; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a); dp[a]++; } for(int i=2;i&