F. Beautiful Rectangle 構造
阿新 • • 發佈:2020-07-28
題解:
本來這個題目不準備寫題解了的,因為這個確實不是很難,但是我wa了很多次之後,發現還是有寫的必要。
這個題目首先求出p和q,這個不是很難求,就是統計每一個數字的數量,然後排序一下,求出每一個寬 x 可以放進去的最多的數量。
求出 p q之後就是構造一個解即可。
但是這個構造要注意 一定是要 row<=col 也就是說 行的數量要小於等於列的數量,而不是列的數量小於等於行的數量。
這個是為什麼呢?
就看看3 5 感性理解一下吧
1 4 7 10 13
14 2 5 8 11
12 15 3 6 9
5 3
1 6 11
12 2 7
8 13 3
4 9 14
15 5 10
對於第二個 5和6 10和11是排在一塊的,而對於第一個則沒有這樣的情況。
#include <bits/stdc++.h> using namespace std; const int maxn = 4e5+10; typedef long long ll; int a[maxn],v[maxn],num[maxn],val[maxn],sum[maxn],c[maxn]; map<int,int>mp[maxn]; bool cmp(int a,int b){ return num[a]>num[b]; } int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &v[i]); a[i] = v[i]; c[i]=i; } sort(v + 1, v + 1 + n); int len = unique(v + 1, v + 1 + n) - v - 1; for (int i = 1; i <= n; i++) { int pos = lower_bound(v + 1, v + 1 + len, a[i]) - v; num[pos]++, val[pos] = num[pos]; } sort(val + 1, val + 1 + len); for (int i = 1; i <= len; i++) { int x = lower_bound(val + 1, val + 1 + len, i) - val; // printf("i=%d x=%d val=%d\n",i,x,val[i]); sum[i] = sum[i - 1] + len - x + 1; } int p = 1, q = 1, maxs = 0; for (int i = 1; i <= sqrt(n); i++) { int res = sum[i] / i * i; if(sum[i]/i<i) continue; // printf("i=%d sum=%d res=%d\n",i,sum[i],res); if (res > maxs) { maxs = res; p = i; q = sum[i] / i; } } // printf("p=%d q=%d\n",p,q); int sx = 0, sy = 0,now = 0; sort(c+1,c+1+len,cmp); for (int i = 1; i <= len; i++) { int id = c[i]; for (int j = 1; j <= min(p, num[id]); j++) { mp[sx][sy] = v[id]; sy=(sy+1)%q, sx=(sx+1)%p; if(!sx){ ++now; sx = 0,sy = now; } } } printf("%lld\n",1ll*p*q); printf("%d %d\n",p,q); for(int i=0;i<p;i++){ for(int j=0;j<q;j++){ printf("%d ",mp[i][j]); } printf("\n"); } }