zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    vb 退出窗口提示
    游戏开发 简介
    gridview 缓存 优化
    Android中Bitmap和Drawable
    解析网络 xml 流程
    vb 检测是否突然断网
    进度条
    网站广告
    android 五大布局
    VB 读写文件
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10052227.html
Copyright © 2011-2022 走看看