POI2008KUP-Plot purchase

POI #Year2008 #贪心 #最大子矩形 #单调栈

先把所有的\(a_{i,j}>2k\)\((i,j)\) 先标记,然后考虑不包含这些点的最大子矩形

如果这个子矩形的 \(sum>k\) 那么必然存在一个合法矩形,可以这样构造

  • 如果当前行的 \(sum_x<k\) 那么删除 \(x\) 这一行
  • 否则当前行合法,输出
// Author: xiaruize
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 2e3 + 10;

int k, n;
int a[N][N];
int sum[N][N];
int up[N];
int top = 0, st[N];

int get(int x, int y, int xx, int yy)
{
	return sum[xx][yy] - sum[x - 1][yy] - sum[xx][y - 1] + sum[x - 1][y - 1];
}

void solve()
{
	cin >> k >> n;
	rep(i, 1, n)
	{
		rep(j, 1, n)
		{
			cin >> a[i][j];
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
		}
	}
	rep(i, 1, n)
	{
		rep(j, 1, n + 1)
		{
			if (a[i][j] <= 2 * k && j <= n)
			{
				up[j]++;
				if (a[i][j] >= k)
				{
					cout << j << ' ' << i << ' ' << j << ' ' << i << endl;
					return;
				}
			}
			else
				up[j] = 0;
			while (top && up[st[top]] >= up[j])
			{
				int y = st[top - 1] + 1, yy = j - 1;
				int x = i - up[st[top]] + 1;
				debug(x, y, i, yy);
				top--;
				if (get(x, y, i, yy) >= k)
				{
					while (get(x, y, i, yy) > 2 * k)
					{
						if (get(x + 1, y, i, yy) > 2 * k)
							x++;
						else
						{
							cout << y << ' ' << x << ' ' << yy << ' ' << x << endl;
							return;
						}
					}
					cout << y << ' ' << x << ' ' << yy << ' ' << i << endl;
					return;
				}
			}
			if (j <= n)
				st[++top] = j;
		}
	}
	cout << "NIE" << endl;
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	// cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}
posted @ 2024-04-15 19:41  xiaruize  阅读(16)  评论(0)    收藏  举报