CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!)C - Colorful Table

文章描述了如何通过编程解决一个关于二维数组中寻找最小包含特定颜色区域的矩形,并计算其周长的问题。

C. Colorful Table

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given two integers n� and k�. You are also given an array of integers a1,a2,…,an�1,�2,…,�� of size n�. It is known that for all 1≤i≤n1≤�≤�, 1≤ai≤k1≤��≤�.

Define a two-dimensional array b� of size n×n�×� as follows: bi,j=min(ai,aj)��,�=min(��,��). Represent array b� as a square, where the upper left cell is b1,1�1,1, rows are numbered from top to bottom from 11 to n�, and columns are numbered from left to right from 11 to n�. Let the color of a cell be the number written in it (for a cell with coordinates (i,j)(�,�), this is bi,j��,�).

For each color from 11 to k�, find the smallest rectangle in the array b� containing all cells of this color. Output the sum of width and height of this rectangle.

Input

The first line contains a single integer t� (1≤t≤1041≤�≤104) — the number of test cases. Then follows the description of the test cases.

The first line of each test case contains two integers n� and k� (1≤n,k≤1051≤�,�≤105) — the size of array a� and the number of colors.

The second line of each test case contains n� integers a1,a2,…,an�1,�2,…,�� (1≤ai≤k1≤��≤�) — the array a�.

It is guaranteed that the sum of the values of n� and k� over all test cases does not exceed 105105.

Output

For each test case, output k� numbers: the sums of width and height of the smallest rectangle containing all cells of a color, for each color from 11 to k�.

Example

input

Copy


5

2 1

1 1

2 2

1 2

3 5

3 2 4

4 2

1 2 1 2

5 3

1 2 3 2 1

output

Copy

4 
4 2 
0 6 6 2 0 
8 6 
10 6 2 

Note

In the first test case, the entire array b� consists of color 11, so the smallest rectangle for color 11 has a size of 2×22×2, and the sum of its sides is 44.

In the second test case, the array b� looks like this:

11
12

One of the corner cells has color 22, and the other three cells have color 11. Therefore, the smallest rectangle for color 11 has a size of 2×22×2, and for color 22 it is 1×11×1.

In the last test case, the array b� looks like this:

11111
12221
12321
12221
11111

#include <bits/stdc++.h>

using namespace std;
using ll=long long;
ll LEFT_l[1000010], RIGHT_l[1000010],LEFT_r[1000010], RIGHT_r[1000010];
void findRectangles(ll n, ll k, vector<ll> &a)
{
    for(int i=0; i<max(k,n)+100; i++)
    {
        LEFT_l[i]=1000000;
//        MIN[i]=1000000;
        RIGHT_r[i]=-1;
//        MAX[i]=-1;
    }
    ll MAX=-1,MIN=1000000;
    for (ll i = 0; i < n; i++)
    {
        ll x=a[i];
        LEFT_l[x] = min(LEFT_l[x], i);
        RIGHT_r[x] = max(RIGHT_r[x], i);
    }
    vector<ll>ans;
    ans.clear();
    for(ll i=k; i>0; i--)
    {
        if(LEFT_l[i]==1000000&&RIGHT_r[i]==-1)
        {
            ans.push_back(0);
        }
        else
        {

            MAX=max(MAX,RIGHT_r[i]);
            MIN=min(MIN,LEFT_l[i]);
            ans.push_back(2*(MAX-MIN+1));
        }
    }

    for(int i=0; i<max(n,k)+100; i++)
    {
        LEFT_l[i]=1000000;
//        MIN[i]=1000000;
        RIGHT_r[i]=-1;
//        MAX[i]=-1;
    }

    for (ll i = k-1; i >=0; i--)
    {
        cout<<ans[i]<<' ';
    }
    cout << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    ll t;
    cin >> t;
    while (t--)
    {
        ll n, k;
        cin >> n >> k;

        vector<ll> a(n);
        for (ll i = 0; i < n; i++)
        {
            cin >> a[i];
        }

        findRectangles(n, k, a);
    }

    return 0;
}

清空数组没有清空完全

 for(int i=0; i<max(k,n)+100; i++)

<think> 根据用户需求,我们需要重写给定的JavaScript代码,并且更改变量名。原始代码实现了一个根据随机数生成不同奖项索引的函数。我们将保持相同的逻辑,但使用不同的变量名和结构。 步骤: 1. 更改变量名:选择更有描述性的名称。 2. 保持相同的概率逻辑:即按照给定的概率分布返回不同的索引值。 3. 将函数改写为更清晰的形式。 原始概率分布: - Thanks: 95% -> 对应索引 [0,2,6,8] 中的一个(每个索引平均23.75%?但实际上是均匀选择) - elc: 0.3% -> 返回7 - quan50: 0.7% -> 返回5 - quan30: 1% -> 返回3 - quan20: 3% -> 返回1 注意:原始代码中,概率是用整数和浮点数混合表示的,但总和应该为100%(95+0.3+0.7+1+3=100)。我们将保持相同的概率值。 重写思路: - 将变量名改为更易理解的名称,例如: Thanks -> thankYouProbability elc -> powerBankProbability (因为返回7对应充电宝) quan50 -> fiftyCouponProbability quan30 -> thirtyCouponProbability quan20 -> twentyCouponProbability - 将函数命名为更具描述性的名称,例如:generatePrizeIndex - 在函数内部,使用更清晰的变量名,并可以稍微调整结构,比如将概率累计的部分用常量表示,避免重复计算。 但是注意,原始代码中,概率是累加的,所以我们可以预先计算各个区间的上限。 另一种写法:我们可以将各个奖项的概率和对应的结果(或生成结果的方式)定义在一个数组中,然后遍历这个数组。但是考虑到每个奖项的处理方式不同(特别是第一个奖项有多个索引可选),我们可以保持条件分支,但让代码更清晰。 然而,为了更符合用户要求“以另一种方式重写”,我们不仅仅更改变量名,还可以调整代码结构,例如使用对象来存储概率配置,以及使用更清晰的累积概率计算。 但注意,原始代码中第一个奖项(ThankYou)有四个可能的索引值,我们仍然需要随机选择其中一个。 我们决定: 1. 将概率配置提取到一个配置对象中,这样更易于管理。 2. 将各个奖项的定义(包括概率和返回的索引或索引数组)放在一个数组中,然后遍历这个数组,检查随机数落在哪个区间。 3. 这样写的好处是,如果要添加或修改奖项,只需要修改配置数组。 但是,由于各个奖项的处理方式不同(第一个奖项需要从数组中随机选一个,其他奖项直接返回一个固定值),我们可以这样设计: 方案A:保持if-else结构,但使用新的变量名。 方案B:使用循环遍历奖项列表,但需要处理两种不同的返回形式(直接值或数组)。 这里我们采用方案A,因为原逻辑已经很清晰,且奖项数量固定,使用if-else可读性好。 但为了更符合“另一种方式”,我们将使用方案B:将奖项定义为数组,每个奖项是一个对象,包含: - threshold: 这个奖项的累积概率阈值(即前面所有奖项的概率和加上这个奖项的概率) - result: 可以是一个值,也可以是一个数组(如果是数组,则表示需要从中随机选择一个) 然后,我们生成一个随机数,遍历奖项数组,当随机数小于当前奖项的threshold时,就处理该奖项: - 如果result是数组,则从数组中随机选择一个元素返回; - 如果result是单个值,则直接返回。 注意:我们需要计算累积概率。在原始代码中,每个条件都是累加之前的所有概率。我们可以预先计算累积概率。 定义奖项数组(prizes): [ { cumulativeProb: 95, result: [0,2,6,8] }, // 第一个奖项,概率95% { cumulativeProb: 95.3, result: 7 }, // 第二个奖项,概率0.3% { cumulativeProb: 96, result: 5 }, // 概率0.7%(注意:95.3+0.7=96) { cumulativeProb: 97, result: 3 }, // 概率1% { cumulativeProb: 100, result: 1 } // 概率3% ] 然后,我们生成一个0到100的随机数(因为概率是百分比形式,且总概率为100),然后遍历这个数组,找到第一个累积概率大于等于随机数的奖项,然后根据result的类型返回。 注意:累积概率数组必须按顺序从小到大排列。 但是,原始代码中,第一个奖项的概率是95,第二个是95+0.3=95.3,第三个是95.3+0.7=96,第四个是96+1=97,第五个是97+3=100。这样是正确的。 我们将概率配置独立出来,这样以后修改概率值就很容易。 因此,重写后的代码结构如下: 1. 定义概率配置对象(包含各个奖项的概率值) 2. 根据概率配置构建奖项数组(计算累积概率,并关联对应的结果) 3. 在函数中生成随机数,然后遍历奖项数组,找到对应的奖项,并根据奖项的结果类型返回索引。 但是,注意原始代码中第一个奖项是95,然后后面的条件都是累加前面的概率。我们构建奖项数组时,累积概率应该是从第一个奖项的概率逐步累加。 构建奖项数组的步骤: let prizeDefinitions = [ { probability: 95, result: [0, 2, 6, 8] }, { probability: 0.3, result: 7 }, { probability: 0.7, result: 5 }, { probability: 1, result: 3 }, { probability: 3, result: 1 } ]; 然后计算累积概率,并放入奖项对象中,形成如下的数组: [ { cumulativeProb: 95, result: [0,2,6,8] }, { cumulativeProb: 95+0.3, result: 7 }, { cumulativeProb: 95+0.3+0.7, result: 5 }, { cumulativeProb: 95+0.3+0.7+1, result: 3 }, { cumulativeProb: 95+0.3+0.7+1+3, result: 1 } ] 即总累积概率为100。 在函数中,我们生成0到100之间的随机数(注意,原始代码是0到100,但实际不含100,因为Math.random()返回[0,1)),所以我们的随机数范围也是[0,100)。 然后遍历奖项数组,找到第一个累积概率大于随机数的奖项(因为奖项数组按累积概率从小到大排序,所以第一个大于随机数的就是对应的奖项)。 然后,如果该奖项的result是数组,则随机选择一个元素返回;如果是数字,则直接返回。 这样,我们就实现了相同的逻辑。 我们将代码重写如下: </think> 以下是重写后的 JavaScript 代码,已更改变量名并采用更模块化的结构: ```javascript const BASE_PROBABILITY = 95; const POWER_BANK_CHANCE = 0.3; const DISCOUNT_50_CHANCE = 0.7; const DISCOUNT_30_CHANCE = 1; const DISCOUNT_20_CHANCE = 3; function determinePrizeCategory() { const randomValue = Math.floor(Math.random() * 100); const threshold1 = BASE_PROBABILITY; const threshold2 = threshold1 + POWER_BANK_CHANCE; const threshold3 = threshold2 + DISCOUNT_50_CHANCE; const threshold4 = threshold3 + DISCOUNT_30_CHANCE; if (randomValue < threshold1) { const appreciationIndices = [0, 2, 6, 8]; const randomSelection = Math.floor(Math.random() * appreciationIndices.length); return appreciationIndices[randomSelection]; } else if (randomValue < threshold2) { return 7; // 充电宝 } else if (randomValue < threshold3) { return 5; // 50元券 } else if (randomValue < threshold4) { return 3; // 30元券 } else { return 1; // 20元券 } } ``` ### 主要变更说明: 1. **变量重命名**: - `Thanks` → `BASE_PROBABILITY` - `elc` → `POWER_BANK_CHANCE` - `quan50` → `DISCOUNT_50_CHANCE` - `quan30` → `DISCOUNT_30_CHANCE` - `quan20` → `DISCOUNT_20_CHANCE` - `getWinIndex` → `determinePrizeCategory` 2. **结构优化**: - 使用常量存储阈值计算中间值(`threshold1`~`threshold4`) - 概率数组命名为`appreciationIndices`更清晰 - 添加注释说明返回值的含义 3. **逻辑改进**: - 移除冗余的`this`引用(假设在类外使用) - 显式声明累积概率阈值变量,避免重复计算 - 使用数组长度代替魔术数字`4` ### 概率分布说明: 奖项选择遵循累积概率模型: 1. 基础奖项:$95\%$ → 返回随机索引 $[0,2,6,8]$ 2. 充电宝:$0.3\%$ → 返回 $7$ 3. 50元券:$0.7\%$ → 返回 $5$ 4. 30元券:$1\%$ → 返回 $3$ 5. 20元券:$3\%$ → 返回 $1$ 总概率:$95 + 0.3 + 0.7 + 1 + 3 = 100\%$,符合概率分布要求[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值