zoukankan      html  css  js  c++  java
  • [暑假集训Day4T2]卡拉赞之夜

    抹茶学长给的标程可以被卡到O(N2M2)???

    考虑二分答案+暴力check+离散化+卡常数

    首先进行离散化,其实判重的话会更快,但是由于矩阵元素大小太大了,hash判重MLE,所以我就直接记录了NM个元素之后排序,即可二分离散化后数组中的下标。

    二分离散化数组的下标,对于每一个下标考虑暴力check。设数组pd,当pd[i][j]=1时,表示F(i,j)>=mid,对于需验证的答案mid,首先令mid--,这样只需判断比mid大的数即可(常数优化)。之后用O(NM)的时间计算pd数组(可以用bitset进行常常数优化,蒟蒻这里不太会,直接开的bool数组)这里有一个很重要的优化,如果一行中1的数量小于2,它一定不能作为矩阵的上界和下界,O(N)记录即可。最后枚举矩阵上下界,设上界为i行,下界为j行,枚举k列。当pd[i][k]==pd[j][k]==1时,可以作为矩阵的两个角,如果两列中列有两组以上这样的情况,那么答案mid是可行的,传回成功信息,如果对于所有行都不行的话,那么传回失败信息。最后,能用快读快写的地方尽量用快读快写,能用位运算的地方尽量用位运算。

    加入以上优化后我成功地把O(N2M(logNM))的算法(N,M≤1000)卡到了568ms(逃)

    参考代码如下:

     1 #include<iostream>
     2 #include<bitset>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cstdlib> 
     6 using namespace std;
     7 inline int read() 
     8 {
     9     int x=0;
    10     bool f=1;
    11     char c=getchar();
    12     for(; !isdigit(c); c=getchar()) if(c=='-') f=0;
    13     for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    14     if(f) return x;
    15     return 0-x;
    16 }
    17 int n,m,f[1010][1010],maxn=-1073741822,minn=1073741822,v[1000001];
    18 inline bool check(int x)
    19 {
    20     x--;
    21     bool p[1010]={},pd[1010][1010]={};
    22     int ct[1010]={};
    23     for(int i=1;i<=n;i++)
    24         for(int j=1;j<=m;j++)
    25             if(f[i][j]>x)pd[i][j]=1,ct[i]++;
    26     for(int i=1;i<=n;i++)
    27     {
    28         if(ct[i]<2)p[i]=1;
    29     }
    30     for(int i=1;i<n;i++)
    31     {
    32         if(p[i])continue;
    33         for(int j=i+1;j<=n;j++)
    34         {
    35             if(p[j])continue;
    36             int cnt=0;
    37             for(int k=1;k<=m;k++)
    38                 if(pd[i][k]&pd[j][k])
    39                 {
    40                     cnt++;
    41                     if(cnt>1) return 1;
    42                 }
    43         }
    44     }
    45     return false;
    46 }
    47 int main()
    48 {
    49     //srand(20050923);
    50     int t=0;
    51     n=read();m=read();
    52     for(int i=1;i<=n;i++)
    53         for(int j=1;j<=m;j++)
    54         {
    55             f[i][j]=read();
    56             v[++t]=f[i][j];
    57             maxn=max(maxn,f[i][j]);
    58             minn=min(minn,f[i][j]);
    59         }
    60     sort(v+1,v+t+1);
    61     int l=1,r=t,mid,tot=0;
    62     while(l<=r)
    63     {
    64         mid=(l+r)>>1;
    65         if(check(v[mid])) l=mid+1;
    66         else r=mid-1;
    67     }
    68     cout<<v[l-1];
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    区块链技术驱动金融.mobi
    ProcessExplorer 工具下载
    免费的论文查重网站
    接口可以继承接口吗?
    比较中的自动拆装箱
    Java语言中的异常处理
    Java类加载过程
    通过反射访问父类的私有成员
    final关键字详解
    MVC 控制台 +log4net 存入数据库
  • 原文地址:https://www.cnblogs.com/szmssf/p/11180858.html
Copyright © 2011-2022 走看看