Codeforces Round 949 (Div. 2) C. Turtle and an Incomplete Sequence 题解 构造

Turtle and an Incomplete Sequence

题目描述

Turtle was playing with a sequence a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an consisting of positive integers. Unfortunately, some of the integers went missing while playing.

Now the sequence becomes incomplete. There may exist an arbitrary number of indices i i i such that a i a_i ai becomes − 1 -1 1. Let the new sequence be a ′ a' a.

Turtle is sad. But Turtle remembers that for every integer i i i from 1 1 1 to n − 1 n - 1 n1, either a i = ⌊ a i + 1 2 ⌋ a_i = \left\lfloor\frac{a_{i + 1}}{2}\right\rfloor ai=2ai+1 or a i + 1 = ⌊ a i 2 ⌋ a_{i + 1} = \left\lfloor\frac{a_i}{2}\right\rfloor ai+1=2ai holds for the original sequence a a a.

Turtle wants you to help him complete the sequence. But sometimes Turtle makes mistakes, so you need to tell him if you can’t complete the sequence.

Formally, you need to find another sequence b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn consisting of positive integers such that:

  • For every integer i i i from 1 1 1 to n n n, if a i ′ ≠ − 1 a'_i \ne -1 ai=1, then b i = a i ′ b_i = a'_i bi=ai.
  • For every integer i i i from 1 1 1 to n − 1 n - 1 n1, either b i = ⌊ b i + 1 2 ⌋ b_i = \left\lfloor\frac{b_{i + 1}}{2}\right\rfloor bi=2bi+1 or b i + 1 = ⌊ b i 2 ⌋ b_{i + 1} = \left\lfloor\frac{b_i}{2}\right\rfloor bi+1=2bi holds.
  • For every integer i i i from 1 1 1 to n n n, 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1bi109.

If there is no sequence b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn that satisfies all of the conditions above, you need to report − 1 -1 1.

输入描述

Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1t105). The description of the test cases follows.

The first line of each test case contains a single integer n n n ( 2 ≤ n ≤ 2 ⋅ 1 0 5 2 \le n \le 2 \cdot 10^5 2n2105) — the length of the sequence.

The second line of each test case contains n n n integers a 1 ′ , a 2 ′ , … , a n ′ a'_1, a'_2, \ldots, a'_n a1,a2,,an ( a i ′ = − 1 a'_i = -1 ai=1 or 1 ≤ a i ′ ≤ 1 0 8 1 \le a'_i \le 10^8 1ai108) — the elements of the sequence a ′ a' a.

It is guaranteed that the sum of n n n over all test cases does not exceed 2 ⋅ 1 0 5 2 \cdot 10^5 2105.

输出描述

For each test case, if there is no sequence b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn that satisfies all of the conditions, output a single integer − 1 -1 1.

Otherwise, output n n n integers b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn — the elements of the sequence b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,,bn you find. The sequence should satisfy that 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1bi109 for every integer i i i from 1 1 1 to n n n. If there are multiple answers, print any of them.

样例 #1

样例输入 #1

9
8
-1 -1 -1 2 -1 -1 1 -1
4
-1 -1 -1 -1
6
3 -1 -1 -1 9 -1
4
-1 5 -1 6
4
2 -1 -1 3
4
1 2 3 4
2
4 2
5
-1 3 -1 3 6
13
-1 -1 3 -1 -1 -1 -1 7 -1 -1 3 -1 -1

样例输出 #1

4 9 4 2 4 2 1 2
7 3 6 13
3 1 2 4 9 18
-1
-1
-1
4 2
6 3 1 3 6
3 1 3 1 3 7 3 7 3 1 3 1 3

原题

CF——传送门

思路&代码

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
typedef long long ll;

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n);
    vector<int> idx;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (a[i] != -1)
            idx.push_back(i); // idx数组保存所有值非-1的下标
    }
    if (idx.empty()) // 特判全是-1的情况
    {
        for (int i = 0; i < n; i++) // 这种情况只需要1和2交替出现即可
        {
            if (i & 1)
                a[i] = 1;
            else
                a[i] = 2;
        }
        for (int i = 0; i < n; i++)
            cout << a[i] << " \n"[i == n - 1];
    }
    else
    {
        auto path = [&](int x, int y) -> vector<int>
        {
            vector<int> left, right; // left和right分别为x到lca的路径和y到lca的路径
            // 先将x和y转移到二叉树的同一层中
            while ((int)log2(x) > (int)log2(y))
            {
                left.push_back(x);
                x >>= 1;
            }
            while ((int)log2(y) > (int)log2(x))
            {
                right.push_back(y);
                y >>= 1;
            }
            // 然后x和y同时向LCA转移
            while (x != y)
            {
                left.push_back(x);
                right.push_back(y);
                x >>= 1;
                y >>= 1;
            }
            // 勿忘加入LCA
            left.push_back(x);
            // 合并left和right两个数组
            for (int i = right.size() - 1; i >= 0; i--)
            {
                left.push_back(right[i]);
            }
            // 返回合并后的数组,即路径
            return left;
        };
        // 第一个值非-1的索引左侧的-1可以通过上一个值交替乘2,除2来构造
        for (int i = idx[0] - 1, cnt = 1; i >= 0; i--, cnt++)
        {
            if (cnt & 1)
                a[i] = a[i + 1] * 2;
            else
                a[i] = a[i + 1] / 2;
        }
        // 最后一个值非-1的索引右侧的-1可以通过上一个值交替乘2,除2来构造
        for (int i = idx[idx.size() - 1] + 1, cnt = 1; i < n; i++, cnt++)
        {
            if (cnt & 1)
                a[i] = a[i - 1] * 2;
            else
                a[i] = a[i - 1] / 2;
        }
        // 对于两个值非-1的索引中间的-1,找到值a[idx[i]]和a[idx[i+1]]的LCA(最近公共祖先),然后存储a[idx[i]]到a[idx[i+1]]的转移路径
        for (int i = 0; i < idx.size() - 1; i++)
        {
            int x = idx[i];
            int y = idx[i + 1];
            vector<int> res = path(a[x], a[y]);
            // 1.如果路径大小的奇偶性和数组内区间元素个数的奇偶性不同,则无法构造(因为若有剩余-1,需要交替*2,/2,而这个操作一定是偶数次)
            // 2.如果路径大小大于数组内区间元素个数,则无法构造,因为-1的数量不足够实现a[idx[i]]到a[idx[i+1]]的转移
            if (((res.size() & 1) ^ ((y - x + 1) & 1)) || (res.size() > (y - x + 1)))
            {
                cout << -1 << '\n';
                return;
            }
            // 如果可以实现构造,先将res路径更新到a数组中
            for (int j = x, cnt = 0; j < x + res.size(); j++, cnt++)
            {
                a[j] = res[cnt];
            }
            // 然后通过交替*2,/2的操作来填补剩余的-1(剩余偶数个-1)
            for (int j = x + res.size(), cnt = 1; j <= y; j++, cnt++)
            {
                if (cnt & 1)
                    a[j] = a[j - 1] * 2;
                else
                    a[j] = a[j - 1] / 2;
            }
        }
        for (int i = 0; i < n; i++)
            cout << a[i] << " \n"[i == n - 1];
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }

    return 0;
}

相关推荐

  1. codeforce#939 (div2) 题解

    2024-06-11 10:44:02       23 阅读
  2. Codeforces Round 941 (Div. 2) ABC

    2024-06-11 10:44:02       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-11 10:44:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-11 10:44:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-11 10:44:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-11 10:44:02       18 阅读

热门阅读

  1. Server-side encryption (SSE)

    2024-06-11 10:44:02       11 阅读
  2. Python实现Stack

    2024-06-11 10:44:02       12 阅读
  3. Git实际应用场景分析

    2024-06-11 10:44:02       13 阅读
  4. .net core webapi跨域

    2024-06-11 10:44:02       8 阅读
  5. 云计算 目录

    2024-06-11 10:44:02       10 阅读
  6. React@16.x(22)HOOK,useState 的原理

    2024-06-11 10:44:02       13 阅读
  7. 【Redis】Redis的数据淘汰策略有哪些

    2024-06-11 10:44:02       11 阅读
  8. SQL的执行顺序

    2024-06-11 10:44:02       8 阅读
  9. Web前端与PHP:深度解析与未来展望

    2024-06-11 10:44:02       11 阅读
  10. 特别名词Test Paper3

    2024-06-11 10:44:02       9 阅读
  11. 微信小程序真机调试连不上

    2024-06-11 10:44:02       7 阅读