首页 > 其他分享 >Animals and Puzzle 题解

Animals and Puzzle 题解

时间:2023-12-19 12:01:43浏览次数:32  
标签:Animals int 题解 Puzzle mid char while return getchar

原题链接:CF713D

题意:给定一个 \(n\times m\) 的地图 \(a\),\(a_{i}\) 为 \(0\) 或 \(1\)。有 \(t\) 次询问,每次询问给定一个矩形,求出这个矩形中最大的由 \(1\) 构成的正方形的边长是多少。

首先考虑预处理出 \(d_{i,j}\) 表示以 \((i,j)\) 为左上角的最大正方形边长是多少。

对于每一次询问可以二分一个 \(mid\),判断 \(mid\) 是否可行就相当于是查询 \(d\) 的一个二维区间中的最大值,如果这个最大值大于等于 \(mid\) 说明可行,否则不可行,注意如果这个二维区间的长宽的最小值比 \(mid\) 小的话,那么肯定不可行。而二维区间 \(\max\) 直接用二维 ST 表维护即可,时间复杂度 \(O(n^{2} \log ^{2}n+t \log n)\)。

预处理 \(d\) 数组可以用 \(O(n^{2} \log n)\) 的二分或者 \(O(n^{2})\) 的 dp。

#include<bits/stdc++.h>
/* --------------- fast io --------------- */ // begin
namespace Fread {
const int SIZE = 1 << 21;
char buf[SIZE], *S, *T;
inline char getchar() {
	if (S == T) {
		T = (S = buf) + fread(buf, 1, SIZE, stdin);
		if (S == T) return '\n';
	}
	return *S++;
}
} // namespace Fread
namespace Fwrite {
const int SIZE = 1 << 21;
char buf[SIZE], *S = buf, *T = buf + SIZE;
inline void flush() {
	fwrite(buf, 1, S - buf, stdout);
	S = buf;
}
inline void putchar(char c) {
	*S++ = c;
	if (S == T) flush();
}
struct NTR {
	~ NTR() { flush(); }
} ztr;
} // namespace Fwrite
#ifdef ONLINE_JUDGE
#define getchar Fread :: getchar
#define putchar Fwrite :: putchar
#endif
namespace Fastio {
struct Reader {
	template<typename T>
	Reader& operator >> (T& x) {
		char c = getchar();
		T f = 1;
		while (c < '0' || c > '9') {
			if (c == '-') f = -1;
			c = getchar();
		}
		x = 0;
		while (c >= '0' && c <= '9') {
			x = x * 10 + (c - '0');
			c = getchar();
		}
		x *= f;
		return *this;
	}
	Reader& operator >> (char& c) {
		c = getchar();
		while (c == ' ' || c == '\n') c = getchar();
		return *this;
	}
	Reader& operator >> (char* str) {
		int len = 0;
		char c = getchar();
		while (c == ' ' || c == '\n') c = getchar();
		while (c != ' ' && c != '\n' && c != '\r') { // \r\n in windows
			str[len++] = c;
			c = getchar();
		}
		str[len] = '\0';
		return *this;
	}
	Reader(){}
} cin;
const char endl = '\n';
struct Writer {
	template<typename T>
	Writer& operator << (T x) {
		if (x == 0) { putchar('0'); return *this; }
		if (x < 0) { putchar('-'); x = -x; }
		static int sta[45];
		int top = 0;
		while (x) { sta[++top] = x % 10; x /= 10; }
		while (top) { putchar(sta[top] + '0'); --top; }
		return *this;
	}
	Writer& operator << (char c) {
		putchar(c);
		return *this;
	}
	Writer& operator << (char* str) {
		int cur = 0;
		while (str[cur]) putchar(str[cur++]);
		return *this;
	}
	Writer& operator << (const char* str) {
		int cur = 0;
		while (str[cur]) putchar(str[cur++]);
		return *this;
	}
	Writer(){}
} cout;
} // namespace Fastio
#define cin Fastio :: cin
#define cout Fastio :: cout
#define endl Fastio :: endl
/* --------------- fast io --------------- */ // end
using namespace std;
#define re register
const int MAXN = 1e3 + 1;
int n,m,sum[MAXN][MAXN],t,x,y,p,q;
bool a[MAXN][MAXN];
short d[MAXN][MAXN],st[MAXN][MAXN][11][11];
inline bool check(int X,int Y,int len)
{
	re int P = X + len - 1,Q = Y + len - 1;
	if(sum[P][Q] - sum[P][Y - 1] - sum[X - 1][Q] + sum[X - 1][Y - 1] == len * len) return true;
	else return false;
}
inline bool solve(int mid)
{
	re int P = p - mid + 1,Q = q - mid + 1;//(x,y),(P,Q)
	int f = __lg(P - x + 1),l = __lg(Q - y + 1);
	if(P < x || Q < y) return false;
	int mx = max(max(st[x][y][f][l],st[P - (1 << f) + 1][y][f][l]),max(st[x][Q - (1 << l) + 1][f][l],st[P - (1 << f) + 1][Q - (1 << l) + 1][f][l]));
//	cout << "x = " << x << " y = " << y << " P = " << P << " Q = " << Q << " " << "max = " << mx << " mid = " << mid<<" f = " << f << " l = " << l << endl;
	if(mx >= mid) return true;
	else return false;
}
signed main()
{
	cin >> n >> m;
	for(int i = 1;i <= n;i++) for(int j = 1;j <= m;j++) cin >> a[i][j];
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
		{
			re int l = 1,r = min(n - i + 1,m - j + 1);
			while(l <= r)
			{
				int mid = (l + r) >> 1;
				if(check(i,j,mid)) d[i][j] = mid,l = mid + 1;
				else r = mid - 1;
			}
			st[i][j][0][0] = d[i][j];
		}
	for(int i = 0;i <= __lg(n) + 1;i++)
		for(int j = 0;j <= __lg(m) + 1;j++)
		{
			if(i == 0 && j == 0) continue;
			for(int s = 1;s <= (n - (1 << i) + 1);s++)
				for(int e = 1;e <= (m - (1 << j) + 1);e++)
				{
//					if(s + (1 << i) > n || e + (1 << j) > m) continue;
					if(i != 0) st[s][e][i][j] = max(st[s][e][i - 1][j],st[s + (1 << i - 1)][e][i - 1][j]);
					else st[s][e][i][j] = max(st[s][e][i][j - 1],st[s][e + (1 << j - 1)][i][j - 1]);
//					cout << s << " " << e << " " << s + (1 << i) - 1 << " " << e + (1 << j) - 1 << " " << st[s][e][i][j] << endl;
				}
		}
	cin >> t;
	while(t--)
	{
		cin >> x >> y >> p >> q;
		int l = 0,r = max(n,m),ans = 0;
		while(l <= r)
		{
			int mid = (l + r) >> 1;
			if(solve(mid) == true) ans = mid,l = mid + 1;
			else r = mid - 1;
		}
		printf("%d\n",ans);
	}
	return 0;
}
/*
3 4
1 1 0 1
0 1 1 0
0 1 1 0
5
1 1 2 3
2 1 3 2
3 2 3 4
1 1 3 4
1 2 3 4
*/

标签:Animals,int,题解,Puzzle,mid,char,while,return,getchar
From: https://www.cnblogs.com/Creeperl/p/17913394.html

相关文章

  • C0392 B 【1109 B组】预处理器 题解
    题意:求有多少个长度为\(n\)的数组\(a\)满足以下条件。条件一:\(l_{i}\lea_{i}\ler_{i}\)。条件二:\(a_{i}\)模\(2\)等于\(p_{i}\)。条件三:\(s\le\suma_{i}\let\)。求答案模\(mod\)的值,\(mod\)不一定是一个质数。数据范围:\(n\le13\)。又积累到一......
  • A Simple Task 题解
    这道题比较简单,简述一下思路。考虑状压\(DP\)。设\(dp_{i,j}\)表示走到第\(i\)个点,之前走过的点的状态为\(j\)的环的数量。这里有一个细节,就是我们都钦定每个走过的第一点是整个状态中编号最小的点,这样不会重复计算。考虑如何进行转移。如果当前点的编号比走过的最小编......
  • CF1900D Small GCD 题解
    原题链接:CF1900D,题意不多赘述。首先可以将\(a\)数组排序,并且枚举中间的那个数\(a_i\)。那么答案就是\(\sum_{j=1}^{i-1}\gcd(a_j,a_i)\times(n-i)\)。重点在于求前面的\(\gcd\)。可以用欧拉反演,但是也可以不用,因为我不会。假设我们当前已经枚举到了\(a_i\),设\(f_k\)表......
  • CF1902D Robot Queries 题解
    题意:有一个二维平面直角坐标系,给定一串向某个方向移动\(1\)个单位的操作。有\(q\)个询问,对于每个询问给定\(x,y,l,r\),问如果倒着做\(l\)到\(r\)这段区间中的操作,是否会经过\((x,y)\)。ds题。先预处理出\(sx_i,sy_i\)表示执行完操作\(i\)后的位置,如果在\([l,r]\)......
  • 华中师范大学2023新生赛 H 龙 题解
    Link华中师范大学2023新生赛H龙Question有\(m\)个宝石孔,有\(n\)个宝石,每个宝石可以提升\(a_i\)点战斗力每次镶嵌一个宝石,被选中的宝石会随机选择一个宝石孔进去,如果这个孔原来有宝石,则原来的宝石会被损坏你可以任意决定镶嵌宝石的顺序,她想知道,如果把着\(n\)颗宝......
  • 华中师范大学2023新生赛 D 身无彩凤双飞翼 题解
    Link华中师范大学2023新生赛D身无彩凤双飞翼Question给出一个\(n\timesm\)的网格,网格上有一些障碍,问最少添加多少障碍才能使\((1,1)\)和\((n,m)\)不连通Solution我好像用了一种和标答不一样的写法我们先对图bfs一次,如果\((1,1)\)不能到达\((n,m)\),则图本来就......
  • CF1905 B Begginer's Zelda 题解
    LinkCF1905BBegginer'sZeldaQuestion给出一棵树,每次能把一条路径压缩成一个点,求最少几次把树压缩成一个点Solution贪心的想,路径肯定越长越好,所以肯定是以一个儿子节点为起点,以一个儿子节点为终点,儿子节点合并了儿子到根的父节点也合并了,每次合并两个儿子节点,假设儿子节点......
  • 【题解】CodeForces-1913
    CodeForces-1913ARatingIncrease依题意模拟。提交记录:Submission-CodeForcesCodeForces-1913BSwapandDelete交换免费就是能任意重排,从头开始尽量填相反的,剩下只能删去了。提交记录:Submission-CodeForcesCodeForces-1913CGamewithMultiset从大到小能减则减一定......
  • 【题解】CodeForces-1905
    CodeForces-1905AConstructiveProblems发现沿着对角线放就行了,答案是\(\max(n+m)\)。提交记录:Submission-CodeForcesCodeForces-1905BBegginer'sZelda最优操作每次删两个叶子(除了最后一次只剩两个节点),所以答案是叶子个数除以二上取整。提交记录:Submission-CodeForc......
  • Java面向对象程序设计(上海交通大学出版社)12章及以后的课后问题解析
    1)Map集合和Collection集合的区别是什么? Map集合和Collection集合都是Java集合框架中的接口,它们之间有一些关键的区别:元素存储方式:Collection:用于存储单一元素的集合接口。它继承自Iterable接口,包含常见的子接口如List、Set。Map:用于存储键值对(key-value......