• [POI2008]KUP-Plot purchase(单调队列)


    题意

    给定k,n,和n*n的矩阵,求一个子矩形满足权值和在[k,2k]之间

     ,

    题解

    这里用到了极大化矩阵的思想。推荐论文《浅谈用极大化思想解决最大子矩阵问题》Orz

    如果有一个元素在[k,2k]之间。直接输出就好。

    否则。把所有大于2k的元素作为障碍点。

    求每一个最大化矩阵。(用单调队列)

    如果这个矩阵权值和大于等于k

    那么这个矩阵一定有一个子矩阵满足条件。这个结论可以证明。

    假设这个矩阵权值和小于等于2k则直接输出这个矩阵。

    否则这个矩阵权值和一定大于2k

    假设这个矩阵去掉第一行后权值和大于k,则去掉第一行后的矩阵继续操作。

    假设权值和小于等于k则矩阵的第一行权值和一定大于k,所以一个一个去除这一行的元素判断即可。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm> 
     6 using namespace std;
     7 const long long N=2010;
     8 long long n,k,a[N][N],book[N][N],sum[N][N],sum1[N][N],top,stack[N],r[N],l[N];
     9 void work(long long x1,long long y1,long long x2,long long y2){
    10     if(sum1[x2][y2]-sum1[x2][y1-1]-sum1[x1-1][y2]+sum[x1-1][y1-1]<=2*k){
    11         cout<<y1<<" "<<x1<<" "<<y2<<" "<<x2;
    12         return ;
    13     }
    14     while(sum1[x2-1][y2]-sum1[x2-1][y1-1]-sum1[x1-1][y2]+sum1[x1-1][y1-1]>=k){
    15         x2--;
    16     }
    17     while(sum1[x2][y2]-sum1[x2][y1-1]-sum1[x2-1][y2]+sum1[x2-1][y1-1]>2*k)y1++;
    18     cout<<y1<<" "<<x2<<" "<<y2<<" "<<x2;
    19 }
    20 int main(){
    21     scanf("%lld%lld",&k,&n);
    22     for(long long i=1;i<=n;i++)
    23         for(long long j=1;j<=n;j++){
    24             scanf("%lld",&a[i][j]);
    25             if(a[i][j]>=k&&a[i][j]<=2*k){
    26                 cout<<j<<" "<<i<<" "<<j<<" "<<i;
    27                 return 0;
    28             }
    29             if(a[i][j]>2*k)book[i][j]=1;
    30             if(book[i][j])sum[i][j]=0;
    31             else sum[i][j]=sum[i-1][j]+1;
    32             sum1[i][j]=sum1[i-1][j]+sum1[i][j-1]-sum1[i-1][j-1]+a[i][j];
    33         }
    34     for(long long i=1;i<=n;i++){
    35         top=0;
    36         for(long long j=1;j<=n;j++){
    37             while(sum[i][j]<sum[i][stack[top]]){
    38                 r[stack[top]]=j-1;
    39                 top--;
    40             }
    41             stack[++top]=j;
    42         }
    43         while(top){
    44             r[stack[top--]]=n;
    45         }
    46         top=0;
    47         for(long long j=n;j>=1;j--){
    48             while(sum[i][j]<sum[i][stack[top]]){
    49                 l[stack[top]]=j+1;
    50                 top--;
    51             }
    52             stack[++top]=j;
    53         }
    54         while(top){
    55             l[stack[top--]]=1;
    56         }
    57         for(long long j=1;j<=n;j++){
    58             if(sum1[i][r[j]]-sum1[i][l[j]-1]-sum1[i-sum[i][j]][r[j]]+sum1[i-sum[i][j]][l[j]-1]>=k){
    59                 work(i-sum[i][j]+1,l[j],i,r[j]);
    60                 return 0;
    61             }
    62         }
    63     }
    64     printf("NIE");
    65     return 0;
    66 }
  • 相关阅读:
    数组指针的一个易错点
    jQuery on()方法
    php 前一天或后一天的日期
    用jQuery监听浏览器窗口的变化
    jquery获取json对象中的key小技巧
    JQuery操作元素的属性与样式及位置
    用JQuery操作元素的style属性
    如何删除jsPlumb连接
    jsPlumb.jsAPI阅读笔记(官方文档翻译)
    Jquery empty() remove() detach() 方法的区别
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9443119.html
Copyright © 2020-2023  润新知