zoukankan      html  css  js  c++  java
  • Wannafly2016-12-27 SPOJ-MINSUB

    题目链接:

    http://www.spoj.com/problems/MINSUB/

    题意:

    给定一个由非负数组成的矩阵M,和一个整数K,对于矩阵M的子矩阵M’,定义min(M’)为M’矩阵中元素的最小值。
    我们需要找出这样一个子矩阵,该矩阵的面积至少为K,且min(M’)最大化。面积的定义为该矩阵的行数*列数。求出min(M’),并给出使得min(M’)为该值时面积的最大值。

    题解:

    这类问题都是可以二分答案的。把小于二分值的位置设为0,其他设为1,那么问题就变成了求全为1的子矩阵的最大面积,这件事情可以用单调栈搞(方法类似于http://www.cnblogs.com/ziyi–caolu/archive/2013/06/23/3151556.html ,事先统计出每个位置向左有多少个1)。可以预处理出每个点(i,j)的左边有多少个连续的1(记为f[i][j]),然后枚举每一列,那么这一列就可以类似与单调栈一样处理算出能上下延伸多少,做法和一 数组的单调栈一样。

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 1e5+10;
    17 
    18 int n,m,k;
    19 int a[1005][1005],f[1005][1005];
    20 
    21 struct node{
    22     int v,pre,nxt;
    23     node(int v) : v(v),pre(1),nxt(1) {}
    24 };
    25 
    26 ll calc(int x){
    27     MS(f);
    28     for(int i=1; i<=n; i++)
    29         for(int j=1; j<=m; j++)
    30             if(a[i][j]>=x) f[i][j] = f[i][j-1]+1;
    31 
    32     ll ans = -1;
    33     for(int j=1; j<=m; j++){
    34         stack<node> s;
    35         s.push(node(f[1][j]));
    36         for(int i=2; i<=n; i++){
    37             node t = node{f[i][j]};
    38             while(!s.empty() && t.v<=s.top().v){
    39                 node tt=s.top(); s.pop();
    40                 if(!s.empty()) s.top().nxt += tt.nxt;
    41                 t.pre += tt.pre;
    42 
    43                 ll tmp = tt.v * (tt.pre+tt.nxt-1);
    44                 if(tmp>ans && tmp>=k)
    45                     ans = tmp;
    46             }
    47             s.push(t);
    48         }
    49         while(!s.empty()){
    50             node tt = s.top(); s.pop();
    51             if(!s.empty()) s.top().nxt += tt.nxt;
    52 
    53             ll tmp = tt.v * (tt.pre+tt.nxt-1);
    54             if(tmp>ans && tmp>=k)
    55                 ans = tmp;
    56         }
    57     }
    58 
    59     return ans;
    60 }
    61 
    62 int main(){
    63     int T = read();
    64     while(T--){
    65         int mi = INF, mx = -INF;
    66         cin >> n >> m >> k;
    67         for(int i=1; i<=n; i++)
    68             for(int j=1; j<=m; j++){
    69                 cin >> a[i][j];
    70                 mi = min(mi,a[i][j]);
    71                 mx = max(mx,a[i][j]);
    72             }
    73         ll ans1=0,ans2=0;
    74         int L=mi,R=mx; 
    75         while(L<=R){
    76             int mid = (L+R)/2;
    77             ll tmp = calc(mid);
    78             if(tmp!=-1) ans1=mid,ans2=tmp,L=mid+1;
    79             else R=mid-1;
    80         }
    81 
    82         cout << ans1 << " " << ans2 << endl;
    83     }
    84 
    85     return 0;
    86 }
  • 相关阅读:
    linux 短信收发
    sama5d3 环境检测 adc测试
    【Codeforces 723C】Polycarp at the Radio 贪心
    【Codeforces 723B】Text Document Analysis 模拟
    【USACO 2.2】Preface Numbering (找规律)
    【Codeforces 722C】Destroying Array (数据结构、set)
    【USACO 2.1】Hamming Codes
    【USACO 2.1】Healthy Holsteins
    【USACO 2.1】Sorting A Three-Valued Sequence
    【USACO 2.1】Ordered Fractions
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827579.html
Copyright © 2011-2022 走看看