• CodeForces 1521E Nastia and a Beautiful Matrix 题解


    CF1521E链接

    这道题有多解,下面给出一种无需二分的做法。

    Hint 1 先假设已经求出了 $size$。

    观察题目所给条件,是否可以把网格分成两部分,使得每部分里互不影响,只需要考虑两部分之间的冲突?

    Hint 2 按行的奇偶性来分,那么网格应当是这样的:
    11111
    2 2 2
    11111
    2 2 2
    11111
    

    怎样安排数字,才能最大化利用上面Hint 1的性质?

    Hint 3 存在一种安排方法,使得只有一种数字 $x$ 可能出现冲突。在放置 $x$ 时,会出现什么问题?如何避免?
    题解 假设 $size$ 为最小边长。

    考虑到 (mat_{i,j} eq mat_{i+1,j+1})(mat_{i,j+1} eq mat_{i+1,j})

    我们将网格按行的奇偶性分成两部分 (S_1), (S_2)

    11111
    2 2 2
    11111
    2 2 2
    11111
    

    发现,每部分里的数字两两不影响,只有两部分间才可能出现冲突。

    然后,我们如果把所有相同的数字放在一起,按某种顺序排好,先填 (S_1), 再填 (S_2),可以做到,只有1种数字 (x) 同时在 (S_1)(S_2) 中出现。理解一下,因为数字是一段一段的,肯定只有一段从中间被分开了。

    顺便算出 (x) 留在 (S_1) 中的个数 (num) (则在 (S_2) 中的有 (cnt_{x} - num) 个)。

    为了不冲突,把(S_1) 里的放在下图 (A) 处,把(S_2)里的放在 (B) 处。

    A A A
    B B B
    A A A
    B B B
    A A A
    

    这会带来新的问题:(S_1) 里最多只能放 (lim = (leftlceildfrac{size}{2} ight ceil)^2) 个,可能不够放。为了避免,我用的方法是:把 (a_i) 排序,按 (a_i) 的降序填数。

    简单证明一下,设 (n geq 2)(cap = size imes leftlceildfrac{size}{2} ight ceil)(S_1) 的大小,则(a_1 geq a_2 geq ... geq a_n)。显然,(a_1) 对应的数字不会成为 (x)

    假设 (x)(a_k) 所对应的,则 (sum1 = a_1 + a_2 + ... + a_{k-1} leq cap)(sum2 = a_1 + a_2 + ... + a_k > cap)。因此 (a_k leq dfrac{cap}{k})。而 (num < a_k)

    (k = 2) 时,(num) 最大值可达 (dfrac{cap}{2}),显然 (lim geq dfrac{cap}{2}) 。可见 (lim) 恒不小于 (num)

    剩下的数字呢?(x) 前面的都放 (S_1),后面的都放 (S_2)

    (size) 的方法还没说呢。上述构造方法可以保证,满足下面两个条件的输入都能找到解。

    1.(m leq size^2 - (leftlfloordfrac{size}{2} ight floor)^2)

    2.(max{a_i} leq cap)

    枚举即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define mit map<int,int>::iterator
    #define sit set<int>::iterator
    #define itrm(g,x) for(mit g=x.begin();g!=x.end();g++)
    #define itrs(g,x) for(sit g=x.begin();g!=x.end();g++)
    #define ltype int
    #define rep(i,j,k) for(ltype(i)=(j);(i)<=(k);(i)++)
    #define rap(i,j,k) for(ltype(i)=(j);(i)<(k);(i)++)
    #define per(i,j,k) for(ltype(i)=(j);(i)>=(k);(i)--)
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mpr make_pair
    #define pb push_back
    #define fastio ios::sync_with_stdio(false)
    #define check(x) if(x>=mod) x-=mod
    const int inf=0x3f3f3f3f,mod=1000000007;
    const double pi=3.1415926535897932,eps=1e-6;
    void chmax(int &x,int y){if(x < y) x = y;}
    void chmin(int &x,int y){if(x > y) x = y;}
    int qpow(int x,int y){
        int ret = 1;
        while(y) {
            if(y & 1) ret = (ll)ret * x % mod;
            x = (ll)x * x % mod;
            y >>= 1;
        }
        return ret;
    }
    int n,m,mx,ans[1005][1005];pii a[100005];
    void solve()
    {
        scanf("%d%d",&m,&n);
        rep(i,1,n) scanf("%d",&a[i].fi),a[i].se = i;
        sort(a+1,a+n+1);reverse(a+1,a+n+1);
        mx = 1;rep(i,2,n) if(a[mx] < a[i]) mx = i;
        int s = 0;while(s * ((s + 1) / 2) < a[mx].fi || (s * s) - ((s / 2) * (s / 2)) < m) s++;
        int cap = s * ((s + 1) / 2);
        int id = n + 1, rest = 0;rep(i,1,n) if(rest + a[i].fi > cap) {id = i;break;} else rest += a[i].fi;
    
        int u = 1, v = 1;
        int num = cap - rest;
        if(id <= n)rep(i,1,num) {
            ans[u][v] = a[id].se;
            v += 2;
            if(v > s) v = 1, u += 2;
        }
        u = 1;v = 1;
        rap(i,1,id) {
            while(a[i].fi){
                if(!ans[u][v]) ans[u][v] = a[i].se, a[i].fi--;
                v++;
                if(v > s) v = 1, u += 2;
            }
        }
        
        u = 2;v = 1;
        if(id <= n) rep(i,1,a[id].fi - num) {
            ans[u][v] = a[id].se;
            v += 2;
            if(v > s) v = 1, u += 2;
        }
        rep(i,id+1,n) {
            while(a[i].fi){
                if(!ans[u][v]) ans[u][v] = a[i].se, a[i].fi--;
                v += 2;
                if(v > s) v = 1, u += 2;
            }
        }
        printf("%d
    ",s);
        rep(i,1,s) rep(j,1,s) printf("%d%c",ans[i][j],j==s?'
    ':' '),ans[i][j] = 0;
    }
    int main()
    {
        int T;scanf("%d",&T);while(T--) solve();return 0;
    }
    
  • 相关阅读:
    intel dpdk在ubuntu12.04中測试testpmd、helloworld程序
    经常使用的MySQL语句整理
    韩国IT业是怎么走向国际我们须要学习什么
    【QT】C++ GUI Qt4 学习笔记3
    【编程之美】2.18 数组分割
    【编程之美】2.8 找符合条件的整数
    【QT】C++ GUI Qt4 学习笔记2
    【QT】C++ GUI Qt4 学习笔记1
    【编程之美】2.7求最大公约数
    【编程之美】2.6 精确表达浮点数
  • 原文地址:https://www.cnblogs.com/yz-beacon-cwk/p/14747377.html
Copyright © 2020-2023  润新知