CodeForces 1706B.Making Towers(思维)

problem description

You have a sequence of n colored blocks. The color of the i-th block is ci , an integer between 1 and n.

You will place the blocks down in sequence on an infinite coordinate grid in the following way.

  1. Initially, you place block 1 at (0,0).
  2. For 2in, if the (i − 1) - th block is placed at position (x, y), then the i-th block can be placed at one of positions (x+1,y), (x−1,y), (x,y+1) (but not at position (x,y−1), as long no previous block was placed at that position.

A tower is formed by s blocks such that they are placed at positions (x,y), (x,y+1),…, (x, y+s−1) for some position and integer s. The size of the tower is s, the number of blocks in it. A tower of color r is a tower such that all blocks in it have the color r.

For each color r from 1 to n, solve the following problem independently:

  • Find the maximum size of a tower of color r that you can form by placing down the blocks according to the rules.
Input

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

The first line of each test case contains a single integer n (1 ≤ n ≤ 105).

The second line of each test case contains n integers c1, c2, …, cn ( 1 ≤ ci ≤ n).

It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.

Output

For each test case, output n integers. The r - th of them should be the maximum size of an tower of color r you can form by following the given rules. If you cannot form any tower of color r, the r - th integer should be 0.


题意
给定一串数字序列,每个数字代表一个色块,相同的数字则是相同颜色的色块。
第一个色块可以摆放在 (x, y) ,接下来的色块只能摆放在上一个色块的左边、右边和上面。
当下一个色块摆放的 y 坐标比上一个相同颜色色块大1时,该种颜色的色块的高度才能 +1. 
统计同种色块的最大高度,将高度输出该色块第一次出现的位置上,其余位置则输出 0. 
思路

找规律,发现 只有当一个色块距离上一个色块的距离为奇数时,该种色块的高度才能+1.
例如:当距离为1时,可以直接放在上一相同色块的上面;当距离为3时,可以 左-上-右 或者 右-上-左 这样放置色块,第三块色块就可以放在上一相同色块的上面


代码如下:
/*
只有一个色块距离上一个色块的距离为奇数,该色块的高度才能+1
*/

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;

int a[N]; //原色块数组
int r[N]; //最后的高度数组
int dp[N]; //上一次访问的位置
int vis[N]; //判断是否访问过

int main()
{
    int t;
    cin >> t;
    while (t--){
        int n;
        cin >> n;

        //初始化
        for (int i = 1; i <= n; i++){
            cin >> a[i];
            r[i] = 0;
            dp[i] = 0;
            vis[i] = 0;
        }

        for (int i = 1; i <= n; i++){
            if (vis[a[i]] == 0) //若该色块未被访问过
            {
                dp[a[i]] = i; //该色块的上一个相同色块位置为它自己
                r[a[i]] = 1; //初始高度为1
            }
            else //若该色块被访问过,即该色块不是第一次出现
            {
                int temp = i; //记录当前位置
                if ((temp - dp[a[i]]) % 2 != 0) //如果该位置与上一个位置的距离为奇数
                {
                    r[a[i]]++; //则高度+1
                    dp[a[i]] = temp; //更新上一个访问位置为当前位置
                }
            }

            vis[a[i]] = 1; //将该色块标记为已访问
        }

        for (int i = 1; i <= n; i++) //输出最后的高度
            cout << r[i] << " ";
        cout << endl;
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BraumAce

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

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

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

打赏作者

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

抵扣说明:

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

余额充值