zoukankan      html  css  js  c++  java
  • bzoj 1127 KUP —— 最大子矩形+答案构造

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

    首先,把权值 > 2*k 的点作为“坏点”,然后在图中用悬线法找权值最大的子矩形;

    如果权值最大的子矩形的权值 < k ,那么无解;

    否则,针对这个子矩形,一列一列地删掉元素,某一时刻权值一定会变成 k~2*k 或 < k;

    如果变成 k~2*k ,直接输出即可;

    如果变成 < k,那么刚才删掉的那一列的权值 > k;

    针对那一列,如果权值和就是 k~2*k,输出那一列;

    否则,针对这一列,一个一个删除元素,因为此时元素的权值都是 < k 的,所以总会有某一时刻删成 k~2*k,即为答案;

    注意输出的坐标是 列-行 !!!

    还要注意一个一个删除列上的元素时,符合答案后的坐标是 i+1 !!!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=2005;
    int n,k,v[xn][xn],l[xn][xn],r[xn][xn],s[xn][xn];
    ll sum[xn][xn];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    ll get(int a,int b,int c,int d){return sum[c][d]-sum[a-1][d]-sum[c][b-1]+sum[a-1][b-1];}
    int main()
    {
      k=rd(); n=rd(); int a=0,b=0,c,d;
      for(int i=1;i<=n;i++)
        {
          int tmp=1;
          for(int j=1;j<=n;j++)
            {
              v[i][j]=rd();
              sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+v[i][j];
              if(v[i][j]>=k&&v[i][j]<=2*k)a=i,b=j;
              if(v[i][j]>2*k){tmp=j+1; continue;}
              s[i][j]=s[i-1][j]+1;
              if(v[i-1][j]>2*k||i==1)l[i][j]=tmp;
              else l[i][j]=max(tmp,l[i-1][j]);
            }
          tmp=n;
          for(int j=n;j;j--)
            {
              if(v[i][j]>2*k){tmp=j-1; continue;}
              if(v[i-1][j]>2*k||i==1)r[i][j]=tmp;
              else r[i][j]=min(tmp,r[i-1][j]);
            }
        }
      if(a){printf("%d %d %d %d
    ",b,a,b,a); return 0;}
      ll mxs=0;
      for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
          {
            if(v[i][j]>2*k)continue;
            int ta=i-s[i][j]+1,tb=l[i][j],tc=i,td=r[i][j];
            ll ts=get(ta,tb,tc,td);
            if(ts<k)continue;
            if(ts>mxs)mxs=ts,a=ta,b=tb,c=tc,d=td;
          }
      if(!mxs){printf("NIE
    "); return 0;}
      if(mxs>=k&&mxs<=2*k){printf("%d %d %d %d
    ",b,a,d,c); return 0;}
      for(int j=b;j<=d;j++)
        {
          mxs-=get(a,j,c,j);
          if(mxs>=k&&mxs<=2*k){printf("%d %d %d %d
    ",j+1,a,d,c); return 0;}
          else if(mxs<k)
            {
              ll ts=get(a,j,c,j);
              if(ts>=k&&ts<=2*k){printf("%d %d %d %d
    ",j,a,j,c); return 0;}
              for(int i=a;i<=c;i++)
                {
                  ts-=v[i][j];
                  if(ts>=k&&ts<=2*k){printf("%d %d %d %d
    ",j,i+1,j,c); return 0;}//i+1!!!
                }
            }
        }
      return 0;
    }
  • 相关阅读:
    查看Android源码版本
    Android中级教程(一)之手机页面的转换setContentView的应用 转
    string 在clone()中的特殊性 (转载)
    关于一个C语言二维数组的问题
    异常机制及throw与throws的区别 (z)
    关于CHelloDoc* GetDocument() 的一些问题 ?
    VC++错误 'OnLButtonDown' : member function not declared in 'CYx2_31View'
    Android中利用LinearLayout继承实现ImageButton 转
    ID 指针 句柄
    句柄和ID 指针与handle的区别
  • 原文地址:https://www.cnblogs.com/Zinn/p/9755343.html
Copyright © 2011-2022 走看看