Codeforces Ilya and Matrix

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

贪心,构造性问题

题意:一开始看错了以为是一个直接递归就能解决的问题,后来才发现,是要构造一个矩阵。给了4^n个数字,然后让你利用这些数字构造出一个2^n*2^n的方阵,并且令到这个方阵的beauty值最大。

一个方阵的beauty值是这样定义的,这个方阵如果只有一个元素,那么它的beauty值就是这个元素,当然这个方阵里面的最大元素也是它。如果这个方阵不止一个元素,这个方阵一定能分割为4个等大的小方阵(因为保证是2^n*2^n的。一定可分割),大方阵的beauty值等于4个小方阵的beauty值相加,再加上大方针中最大元素。你的目的是要构造一个方阵,让它的beauty值最大

bea值的计算递归即可,但是细想一下bea值的计算过程就能得到构造的策略

会发现,方阵中的每个元素都会最后的beauty值做出贡献,但是不同元素做出的贡献不同

好像1个2*2的方阵,3个元素对方阵的bea值贡献了1次,而最大值元素则贡献了2次。如果方阵规模再大点,会发现一些元素贡献了4次,一些元素贡献了3次,一些2次,一些1次

所以为了使beauty值最大,我们让较大的元素贡献的次数多一点,这样就能令最大的beauty更大(这就是本题贪心的部分)

下面举几个例子

1*1规模的矩阵

1个元素贡献了1次

2*2规模的矩阵

1个元素贡献2次,3个元素贡献1次

4*4规模的矩阵

1个元素贡献3次,3个元素贡献2次,12个元素贡献1次

8*8规模的矩阵

1个元素贡献4次,3个元素贡献3次,12个元素贡献2次,48个元素贡献1次

 

规律更明显了,我们只要用一些数组把规律保存下来,就能直接使用,具体看代码

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;



typedef long long ll;

const int N  = 2000010;

ll a[N],M[30],C[30],sum[30];



bool cmp(ll x ,ll y){

    return x > y;

}



int main()

{

    M[1] = 1;

    for(int i=2; i<=15; i++) M[i] = M[i-1] * 4;

    C[1] = 1; C[2] = 3;

    for(int i=3; i<=15; i++) C[i] = C[i-1] * 4;

    sum[0] = 0; sum[1] = 1;

    for(int i=2; i<=15; i++) sum[i] = sum[i-1] + C[i];



    int tot,n;

    cin >> tot;

    for(int i=1; i<=tot; i++)

        cin >> a[i];

    sort(a+1,a+1+tot,cmp);

    

    for(int i=1; true ;i++) 

        if(tot == M[i]){

            n = i; break;

        }

    //n是它的规模

    ll res = 0;

    int i=0 , j , k , m = n;

    for(k=1; i<=tot ;k++)

    {

        for(i=sum[k-1]+1; i<=sum[k] && i<=tot; i++)

            res += a[i] * m;

        m--;

    }

    cout << res << endl;

    return 0;

}

 

你可能感兴趣的:(codeforces)