10. 【Codeforces Round 938 (Div. 3)】B.渐进式广场

B.渐进式广场B.渐进式广场B.渐进式广场 每次测试时限:2秒每次测试时限:2 秒每次测试时限:2 每次测试的内存限制:256兆字节每次测试的内存限制:256 兆字节每次测试的内存限制:256兆字节


题目描述

大小为 nnn 的累进正方形是一个 n×nn \times nn×n 矩阵。马克西姆选择三个整数 a1,1a_{1,1}a1,1cccddd ,并根据以下规则构造一个累进正方形:

ai+1,j=ai,j+c a_{i+1,j} = a_{i,j} + c ai+1,j=ai,j+c

ai,j+1=ai,j+d a_{i,j+1} = a_{i,j} + d ai,j+1=ai,j+d

例如,如果 n=3n = 3n=3a1,1=1a_{1,1} = 1a1,1=1c=2c=2c=2d=3d=3d=3 ,那么递进方格如下:

(1473695811) \begin{pmatrix} 1 & 4 & 7 \\ 3 & 6 & 9 \\ 5 & 8 & 11 \end{pmatrix} 1354687911

上个月,马克西姆构建了一个递阶方阵,并记住了 nnncccddd 的值。最近,他发现了一个由 n2n^2n2 个整数随机排列而成的数组 bbb ,并想确定这些元素就是那个特定正方形的元素。

可以证明,对于 nnna1,1a_{1,1}a1,1cccddd 中的任意值,恰好存在一个满足所有规则的递进正方形。


输入

第一行包含一个整数 ttt ( 1≤t≤1041 \le t \le {10} ^ 41t104 ) - 测试用例的数量。

每个测试用例的第一行包含三个整数 nnncccddd ( 2≤n≤5002 \le n \le 5002n500 , 1≤c,d≤1061 \le c, d \le 10^61c,d106 )–正方形的大小以及语句中描述的 cccddd 的值。

每个测试用例的第二行包含 n⋅nn \cdot nnn 个整数 b1,b2,…,bn⋅nb_1, b_2, \dots, b_{n \cdot n}b1,b2,,bnn ( 1≤bi≤1091 \le b_i \le 10^91bi109 ) - 马克西姆找到的元素。

保证所有测试用例中 n2n ^ 2n2 的总和不超过 25⋅10425 \cdot {10} ^ 425104


输出

对于每个测试用例,如果可以用数组元素 aaa 构建出给定的 nnncccddd 的渐进正方形,则另起一行输出 “是”,否则输出 “否”。

您可以以任何大小写(小写或大写)输出每个字母。例如,字符串 “yEs”、“yes”、"Yes "和 "YES "将被视为肯定答案。


思路:我们可以发现当最小值确定时,它所对应的累进正方形里面的各个值也就跟着确定下来了。所以可以先找到给定数组中的最小值,然后利用该最小值去推出正确的累进正方形中的值因该是什么,然后与给定的数组中的元素去比较就可以了。
细节:这道题目要注意一个很重要的细节——>不要使用unordered_map要使用map
为什么呢?这是因为unordered_map是通过哈希表实现的,虽然平均时间复杂度为O(1)O(1)O(1),但是不太稳定,当数据比较刁钻或者设计的哈希函数不合理的时候,会使得各个键值对的键带入哈希函数得到的哈希值始终相同,从而使得所有键值对始终存储在同一链表上,这样会导致时间复杂度降为O(n)O(n)O(n)

map是通过红黑树实现的,虽然平均时间复杂度为O(logn)O(logn)O(logn),但是非常的稳定。

下图中第二个是使用了map,第一个是使用了unordered_map
在这里插入图片描述

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 

bool solve()
{
    int Min=2e9;
    map<int,int>mp;  //注意这里必须要用map,不要使用unordered_map
    int n,c,d; cin>>n>>c>>d;
    for(int i=1;i<=n*n;i++)
    {
        int temp; cin>>temp;
        mp[temp]++;
        Min=min(Min,temp);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            if(mp[Min+(j-1)*d]==0)return false;
            else mp[Min+(j-1)*d]--;
        Min+=c;
    }
    return true;
}

int main()
{
    int t; cin>>t;
    while(t--)
    {
        if(solve())cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

古葬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值