[C++]Codeforces round826(Div 3) A~D题解

A. Compare T-Shirt Sizes

[原题]

Two T-shirt sizes are given: a and b. The T-shirt size is either a string M or a string consisting of several (possibly zero) characters X and one of the characters S or L.

For example, strings M, XXL, S, XXXXXXXS could be the size of some T-shirts. And the strings XM, LL, SX are not sizes.

The letter M stands for medium, S for small, L for large. The letter X refers to the degree of size (from eXtra). For example, XXL is extra-extra-large (bigger than XL, and smaller than XXXL).

You need to compare two given sizes of T-shirts a and b.

The T-shirts are compared as follows:

  • any small size (no matter how many letters X) is smaller than the medium size and any large size;
  • any large size (regardless of the number of letters X) is larger than the medium size and any small size;
  • the more letters X before S, the smaller the size;
  • the more letters X in front of L, the larger the size.

For example:

  • XXXS < XS
  • XXXL > XL
  • XL > M
  • XXL = XXL
  • XXXXXS < M
  • XL > XXXS

Input

The first line of the input contains a single integer t

(1≤t≤104

) — the number of test cases.

Each test case consists of one line, in which a

and b T-shirt sizes are written. The lengths of the strings corresponding to the T-shirt sizes do not exceed 50

. It is guaranteed that all sizes are correct.

Output

For each test case, print on a separate line the result of comparing a

and b T-shirt sizes (lines "<", ">" or "=" without quotes).

[解题思路]

        两两比较字符串的最后一个字符大小('L'>'M'>'S'),若相等则根据题意比较字符串长度,分类并作出判断。

[代码实现]

#include <iostream>
using namespace std;

int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    return x * f;
}

int main()
{
    int t = read();
    while(t--)
    {
        string str1, str2;
        cin >> str1 >> str2;
        char c1 = str1.back(), c2 = str2.back();
        int m = str1.length(), n = str2.length();
        if(c1 == 'S')
        {
            if(c2 == 'S')
            {
                if(m < n)
                    printf(">\n");
                else if(m == n)
                    printf("=\n");
                else
                    printf("<\n");
                continue;
            }
            else
            {
                printf("<\n");
                continue;
            }
        }
        else if(c1 == 'M')
        {
            if(c2 == 'S')
                printf(">\n");
            else if(c2 == 'M')
                printf("=\n");
            else
                printf("<\n");
            continue;
        }
        else
        {
            if (c2 == 'L')
            {
                if (m > n)
                    printf(">\n");
                else if (m == n)
                    printf("=\n");
                else
                    printf("<\n");
                continue;
            }
            else
            {
                printf(">\n");
                continue;
            }
        }
    }
    return 0;
}

B. Funny Permutation

[原题]

A sequence of n numbers is called permutation if it contains all numbers from 1 to n exactly once. For example, the sequences [3,1,4,2], [1] and [2,1] are permutations, but [1,2,1], [0,1] and [1,3,4]

are not.

For a given number n you need to make a permutation p such that two requirements are satisfied at the same time:

        For each element pi, at least one of its neighbors has a value that differs from the value of pi by one. That is, for each element pi (1≤i≤n), at least one of its neighboring elements (standing to the left or right of pi) must be pi+1, or pi−1.

        the permutation must have no fixed points. That is, for every i (1≤i≤n), pi≠i must be satisfied.

Let's call the permutation that satisfies these requirements funny.

For example, let n=4. Then [4,3,1,2] is a funny permutation, since:

        to the right of p1=4 is p2=p1−1=4−1=3;

        to the left of p2=3 is p1=p2+1=3+1=4;

        to the right of p3=1 is p4=p3+1=1+1=2;

        to the left of p4=2 is p3=p4−1=2−1=1.

        for all i is pi≠i.

For a given positive integer n, output any funny permutation of length n, or output -1 if funny permutation of length n does not exist.

Input

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

The description of the test cases follows.

Each test case consists of f single line containing one integer n (2≤n≤2⋅105).

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

Output

For each test case, print on a separate line:

        any funny permutation p of length n;

        or the number -1 if the permutation you are looking for does not exist.

[解题思路]

        当且仅当n为3时找不到合适的组合;对于n为偶数,其逆序排列即为一个满足条件的滑稽序列;对于n为不为3的奇数,我们将正序序列从中间切开并颠倒次序即可得到一个满足条件的滑稽序列,如n为5时,有34512,即由12345切开为12和345并颠倒次序后组合所得。

[代码实现]

#include<iostream>
#include<vector>
using namespace std;

int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    return x * f;
}

int main()
{
    int t = read();
    while(t--)
    {
        int n = read();
        if (n == 3)
        {
            printf("-1\n");
            continue;
        }
        else if(n & 1)
        {
            for (int i = (n >> 1) + 1; i <= n; i++)
            {
                printf("%d ", i);
            }
            for (int i = 1; i <= (n >> 1); i++)
            {
                printf("%d ", i);
            }
            printf("\n");
            continue;
        }
        else
        {
            for (int i = n; i > 0; i--)
            {
                printf("%d ", i);
            }
            printf("\n");
            continue;
        }
    }
    return 0;
}

C. Minimize the Thickness

[原题]

You are given a sequence a=[a1,a2,…,an] consisting of n positive integers.

Let's call a group of consecutive elements a segment. Each segment is characterized by two indices: the index of its left end and the index of its right end. Denote by a[l,r] a segment of the sequence a with the left end in l and the right end in r, i.e. a[l,r]=[al,al+1,…,ar].

For example, if a=[31,4,15,92,6,5], then a[2,5]=[4,15,92,6], a[5,5]=[6], a[1,6]=[31,4,15,92,6,5] are segments.

We split the given sequence a into segments so that:

  • each element is in exactly one segment;
  • the sums of elements for all segments are equal.

For example, if a = [55,45,30,30,40,100], then such a sequence can be split into three segments: a[1,2]=[55,45], a[3,5]=[30,30,40], a[6,6]=[100]. Each element belongs to exactly segment, thesum of the elements of each segment is 100.

Let's define thickness of split as the length of the longest segment. For example, the thickness of the split from the example above is 3.

Find the minimum thickness among all possible splits of the given sequence of a into segments in the required way.

Input

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

Each test case is described by two lines.

The first line of each test case contains a single integer n (1≤n≤2000) — the length of the sequence a.

The second line of each test case contains exactly n integers: a1,a2,…,an (1≤ai≤106) — elements of the sequence a.

It is guaranteed that the sum of n for all test cases does not exceed 2000.

Output

For each test case, output one integer — the minimum possible thickness of a split of the sequence ainto segments.

Note that there always exist a split, you can always consider whole sequence as one segment.

[解题思路]

        由于要将序列分割成一个或多个总和相等的连续子序列,不难发现,序列总和必能被子序列总和整除。因此,我们可以从首位置开始枚举子序列总和(即依次对所有元素进行加和),对于能被序列总和整除的子序列总和,我们对当前状态进行深度优先搜索,并维护其中最长的片段(即thickness),最终得出答案。

[代码实现]

#include<iostream>
using namespace std;
const int maxn = 2100;
typedef long long ll;

ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    return x * f;
}

ll arr[maxn], n;
int ans;

bool FindLongest(ll base, ll pos, int& longest)
{
    ll s = 0;
    int length = 0;
    for (ll i = pos; i <= n; i++)
    {
        s += arr[i];
        length++;
        if(s > base)
            return false;
        else if(s == base)
        {
            longest = max(longest, length);
            if(i == n)
                return true;
            return FindLongest(base, i + 1, longest);
        }
    }
    return false;
}

int main()
{
    ll t = read();
    while(t--)
    {
        n = read();
        ll base = 0, sum = 0;
        ans = n;
        for (ll i = 1; i <= n; i++)
        {
            arr[i] = read();
            sum += arr[i];
        }
        for (ll i = 1; i < n; i++)
        {
            base += arr[i];
            if(sum % base == 0)
            {
                int longest = i;
                if(FindLongest(base, i+1, longest))
                {
                    ans = min(ans, longest);
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

D. Masha and a Beautiful Tree

[原题]

The girl named Masha was walking in the forest and found a complete binary tree of height n and a permutation p of length m=2^n.

A complete binary tree of height n is a rooted tree such that every vertex except the leaves has exactly two sons, and the length of the path from the root to any of the leaves is n. The picture below shows the complete binary tree for n=2.

A permutation is an array consisting of n different integers from 1 to n. For example, [2,3,1,5,4] is a permutation, but [1,2,2] is not (2 occurs twice), and [1,3,4] is also not a permutation (n=3, but there is 4 in the array).

Let's enumerate m leaves of this tree from left to right. The leaf with the number i contains the value pi (1≤i≤m).

For example, if n=2, p=[3,1,4,2], the tree will look like this:

Masha considers a tree beautiful if the values in its leaves are ordered from left to right in increasing order.

In one operation, Masha can choose any non-leaf vertex of the tree and swap its left and right sons (along with their subtrees).

For example, if Masha applies this operation to the root of the tree discussed above, it will take the following form:

Help Masha understand if she can make a tree beautiful in a certain number of operations. If she can, then output the minimum number of operations to make the tree beautiful.

Input

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

In each test case, the first line contains an integer m (1≤m≤262144), which is a power of two  — the size of the permutation p.

The second line contains m integers: p1,p2,…,pm (1≤pi≤m) — the permutation p.

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

Output

For each test case in a separate line, print the minimum possible number of operations for which Masha will be able to make the tree beautiful or -1, if this is not possible.

[解题思路]

        对于一个高度为n的满二叉树,假设其共有8个叶子结点,则对于它根节点的一次交换操作,可以将其前四个元素与后四个元素交换,层数向下,每一次交换操作便可以实现将前两个元素与后两个元素交换,到了倒数第二层,则为将前一个元素与后一个元素交换。由此可见,每个结点管辖的元素个数是随着层数不断减半,因此我们肯定需要对整个区间进行二分来进行判断。

        另外,我们可以观察元素每次分成的两个组:显然,对于根节点的交换操作,我们必须满足1、2、3、4在同一组,5、6、7、8在另一组,否则便不可能形成一棵“漂亮的树”;同理,1、2必须在同一组,而3、4则在另一组......

        因此,我们可以从中发现他们数字和的规律:设当前二分后前后各组的元素个数为k,则有

abs(组1的元素总和 - 组2的元素总和) == k * k

        由于我们需要得到的是单调递增的序列,那么当这两个组本身就满足后一个组的数字和 > 前一个组的数字和时,则没必要将两个组交换,反之则需要进行一次交换操作。

        最后,由于我们频繁地使用了部分子序列的数字和,因此我们可以使用前缀和来优化这个过程。

[代码实现]

#include <iostream>
using namespace std;
const int maxn = 3e6;
typedef long long ll;

ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - 48;
        ch = getchar();
    }
    return x * f;
}

ll arr[maxn], prefix[maxn];

bool check(int &op, ll l, ll r)
{
    if (l == r)
        return true;
    ll mid = l + r >> 1;
    ll k = r - l + 1 >> 1;
    if (prefix[r] - prefix[mid] - (prefix[mid] - prefix[l - 1]) == k * k)
    {
        if (k == 1)
            return true;
        return check(op, l, mid) & check(op, mid + 1, r);
    }
    else if (prefix[mid] - prefix[l - 1] - (prefix[r] - prefix[mid]) == k * k)
    {
        op++;
        if (k == 1)
            return true;
        return check(op, l, mid) & check(op, mid + 1, r);
    }
    return false;
}

int main()
{
    ll t = read();
    while (t--)
    {
        ll m = read();
        for (ll i = 1; i <= m; i++)
        {
            arr[i] = read();
            prefix[i] = prefix[i - 1] + arr[i];
        }
        int op = 0;
        if (check(op, 1, m))
        {
            printf("%d\n", op);
        }
        else
        {
            printf("-1\n");
        }
    }
    return 0;
}
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值