1127: [POI2008]KUP

1127: [POI2008]KUP

https://lydsy.com/JudgeOnline/problem.php?id=1127

分析:

  如果存在一个点大于等于k,小于等于2k的话,直接输出。

  否则把点分成两类,一类是<k的,另一类是大于2k的,大于2k的一定没用。

  然后找一个全部由小于2k的点中组成一个的矩形(悬线法),这个矩形有三种情况:1、<k,没用;2、大于等于k,小于等于2k,输出;3、大于2k,它的子矩阵中一定存在一个合法的矩阵(因为每个元素都是<k的,所以增加一个元素不可能直接使面积从小于k变成大于等于2k)。

  考虑如何对一个大于等于2k的矩形找到它的合法的子矩阵。每次删掉一行或者一列一定可以找到。

  

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 #include<cstdlib>
12 using namespace std;
13 typedef long long LL;
14 
15 inline int read() {
16     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
17     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
18 }
19 
20 const int N = 2005;
21 
22 LL sum[N][N], k;
23 int a[N][N], U[N][N], L[N], R[N], n;
24 
25 void pd(int u,int d,int l,int r) {
26     if (u > d || l > r) return ;
27     LL now = sum[d][r] - sum[d][l - 1] - sum[u - 1][r] + sum[u - 1][l - 1];
28     if (now < k) return ;
29     if (now >= k && now <= k + k) {
30         printf("%d %d %d %d",l, u, r, d); exit(0);
31     }
32     if (d - u > r - l) {
33         pd(u + 1, d, l, r); pd(u, d - 1, l, r);
34         pd(u, d, l + 1, r); pd(u, d, l, r - 1);
35     }
36     else {
37         pd(u, d, l + 1, r); pd(u, d, l, r - 1);
38         pd(u + 1, d, l, r); pd(u, d - 1, l, r);
39     }
40 }
41 
42 int main() { 
43     k = read(), n = read();
44     for (int i = 1; i <= n; ++i) 
45         for (int j = 1; j <= n; ++j) {
46             a[i][j] = read();
47             sum[i][j] = a[i][j] + sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
48             if (a[i][j] >= k && a[i][j] <= k + k) { printf("%d %d %d %d
",j, i, j, i); return 0; }
49         }
50     for (int i = 1; i <= n; ++i)
51         for (int j = 1; j <= n; ++j) 
52              U[i][j] = a[i][j] <= k + k ? U[i - 1][j] + 1 : 0;
53     for (int i = 1; i <= n; ++i) L[i] = 0, R[i] = n + 1;
54     for (int i = 1; i <= n; ++i) {
55         int last = 0;
56         for (int j = 1; j <= n; ++j) {
57              if (a[i][j] <= k + k) L[j] = max(L[j], last + 1);
58              else last = j, L[j] = 0;
59         }
60         last = n + 1;
61         for (int j = n; j >= 1; --j) {
62             if (a[i][j] <= k + k) R[j] = min(R[j], last - 1);
63             else last = j, R[j] = n + 1;
64         }
65         for (int j = 1; j <= n; ++j) 
66             if (U[i][j] && L[j] >= 1 && R[j] <= n) pd(i - U[i][j] + 1, i, L[j], R[j]);
67     }
68     puts("NIE");
69     return 0;
70 }
原文地址:https://www.cnblogs.com/mjtcn/p/10052227.html