【BZOJ5085】最大
Description
给你一个n×m的矩形,要你找一个子矩形,价值为左上角左下角右上角右下角这四个数的最小值,要你最大化矩形的价值。
Input
第一行两个数n,m,接下来n行每行m个数,用来描述矩形
n, m ≤ 1000
Output
输出一个数表示答案
Sample Input
2 2
1 2
3 4
1 2
3 4
Sample Output
1
题解:我们先将所有数排序,然后从大到小扔到矩形中。每当我们加入一个点时,我们枚举它能和同行中的所有点形成的点对。比如有一行有两个点(x1,y1)和(x1,y2),那么就形成了一个点对(y1,y2)。那么一旦某个点对出现了两次,则说明出现了一个矩形。那么我们就不断扔,直到出现某个重复的点对为止,时间复杂度$O(n^2log_n)$。
然而似乎有个结论,答案一定在最大的4*n个点之中。那么取出这些点暴力即可。如果用nth_element+如上做法的话,时间复杂度可以从$O(16*n^2)$优化到$O(n^2)$(然而并不想卡这个常数)。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> using namespace std; int n,m,tot; struct node { int x,y,val; }p[1000010]; int map[1010][1010]; vector<int> v[1010]; vector<int>::iterator it; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } bool cmp(const node &a,const node &b) { return a.val>b.val; } int main() { n=rd(),m=rd(); int i,j; for(i=1;i<=n;i++) for(j=1;j<=m;j++) p[++tot].x=i,p[tot].y=j,p[tot].val=rd(); sort(p+1,p+n*m+1,cmp); for(i=1;i<=tot;i++) { for(it=v[p[i].x].begin();it!=v[p[i].x].end();it++) { if(map[p[i].y][*it]) { printf("%d",p[i].val); return 0; } map[p[i].y][*it]=map[*it][p[i].y]=1; } v[p[i].x].push_back(p[i].y); } }