Codeforces 1276C / 1277F Beautiful Rectangle (configuration)

Topic Link

http://codeforces.com/contest/1276/problem/C

answer

Ah, before the end of the game 3min think of practice and then rush out after the end of the game ...... I wrote 15min just over ......
Here is my approach:
the number of rows and columns set the optimal solution are \ (R \) and \ (C \) , may wish to set \ (R \ Le C \) . for each number then obviously we can only choose no more than \ (R \) months.
Consider all the numbers appear descending order by number, enumeration \ (R & lt \) , the number of available numbers is obtained, to \ (CNT \) , then clearly \ (C \ le \ frac { cnt} {R & lt} \) .
we can constructed proof, \ (C \) can take the \ (\ lfloor \ FRAC {CNT} {R & lt} \ rfloor \) .
the following, for convenience default \ (CNT \) has been removed the \ (\ mod R \) the remainder.
The number of all descending order according to the number of times successively appear together into a sequence (there have been a number on how many times how many copies). Then for any \ (0 \ Le X \ R & lt lt, 0 \ Le Y \ C lt \) , we will first sequence \ ((xC + y) \ ) number into Matrices \ (Y \) line The first\ ((x + y) \ mod C \) column, wherein both the matrix and the sequence of coordinates from \ (0 \) starts. In this way we can prove that certain conditions are met.
Examples explain: Suppose \ (12 \) number of aligned \ (3 \ times 4 \) matrix, the matrix of each index number in the original sequence is:

0 3 6 9
10 1 4 7
8 11 2 5

Proof of correctness: For the same number, it is clear that the position in the sequence satisfies either all \ (X \) are the same, either \ (X \) of a suffix and \ ((x + 1) \ ) period prefix put together, and the length does not exceed \ (R & lt \) .
If the former, obviously accuracy. If the latter, the only circumstances which may affect the validity of that \ (x \) a part number suffix and \ (y \) a part number prefix placed on the same column.
Obviously, this situation is only equal to the number of occurrences \ (R \) appears (because every time is the right one overall), but because we are descending order according to the number of construction icons appear, so there are times when \ (R \) have been placed in front of the sequence, this time because the number has already been put are \ (R & lt \) multiples, so that from a certain \ (0 \) line start discharge, belongs to the first Happening. Therefore, this problem does not occur the second case, proof.
Therefore, each enumeration \ (R & lt \) , to obtain the corresponding \ (C \) , takes a maximum value, and then to take the maximum value of \ (R & lt \) executing the algorithm can be configured.
Time complexity \ (O (the n-\ the n-log) \) , the bottleneck that occurs many times each number after the discrete statistics.

Code

Because it is very cool to rush out so well written chaotic ......

#include<bits/stdc++.h>
#define llong long long
#define pii pair<int,int>
#define mkpr make_pair
using namespace std;
 
inline int read()
{
    int w=1,s=0;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch)) {s=s*10+ch-'0';ch=getchar();}
    return w*s;
}
 
const int N = 1e6;
pii num[N+3];
int cans[N+3];
int fans[N+3];
vector<int> disc;
int a[N+3];
int n,wei;
 
int gcd(int x,int y) {return y==0?x:gcd(y,x%y);}
 
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%d",&a[i]),disc.push_back(a[i]);
    sort(disc.begin(),disc.end()); disc.erase(unique(disc.begin(),disc.end()),disc.end());
    for(int i=1; i<=n; i++) a[i] = lower_bound(disc.begin(),disc.end(),a[i])-disc.begin()+1;
    for(int i=1; i<=n; i++) num[i].second = i;
    for(int i=1; i<=n; i++) num[a[i]].first++;
    sort(num+1,num+n+1);
    int l = 1,r = 0,cnt = 0,ans = 0,mxr = 1;
    for(int i=1; i<=n; i++)
    {
        while(l<=n && num[l].first<i) {l++;}
        cnt += n-l+1;
        if(cnt/i<i) break;
        int cur = cnt/i*i;
        if(cur>ans) {ans = cur; mxr = i;}
    }
    int mxc = ans/mxr;
    printf("%d\n%d %d\n",ans,mxr,mxc);
    l = 1; while(l<=n && num[l].first<1) {l++;}
    int x = 0,y = 0; wei = 0;
    for(int i=n; i>=l; i--)
    {
        int cnt = min(num[i].first,mxr);
        for(int j=1; j<=cnt&&wei<=ans; j++,wei++)
        {
            cans[x*mxc+(x+y)%mxc] = disc[num[i].second-1]; x++; if(x==mxr) {y++,x=0;}
        }
    }
    for(int i=0; i<ans; i++)
    {
        printf("%d ",cans[i]);
        if((i+1)%mxc==0) puts("");
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/12041672.html