Codeforces Round #396 (Div. 2)题解(ABCD)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27008079/article/details/55051564

A. Mahmoud and Longest Uncommon Subsequence

题目链接
While Mahmoud and Ehab were practicing for IOI, they found a problem which name was Longest common subsequence. They solved it, and then Ehab challenged Mahmoud with another problem.

Given two strings a and b, find the length of their longest uncommon subsequence, which is the longest string that is a subsequence of one of them and not a subsequence of the other.

A subsequence of some string is a sequence of characters that appears in the same order in the string, The appearances don’t have to be consecutive, for example, strings “ac”, “bc”, “abc” and “a” are subsequences of string “abc” while strings “abbc” and “acb” are not. The empty string is a subsequence of any string. Any string is a subsequence of itself.

Input

The first line contains string a, and the second line — string b. Both of these strings are non-empty and consist of lowercase letters of English alphabet. The length of each string is not bigger than 105 characters.

Output

If there’s no uncommon subsequence, print “-1”. Otherwise print the length of the longest uncommon subsequence of a and b.

Examples

Input

abcd defgh

Output

5


Input

a a

Output

-1

题意:
求两个字符串之间不同子串的最大长度。

思路:

  1. 两个字符串长度不等,答案为大的长度。
  2. 两个字符串长度相等,若两个字符串不相同,答案为共同的长度,否则为-1。

程序代码:

#include<iostream>
using namespace std;
int main()
{
    string str1, str2;
    int i;
    cin >> str1 >> str2;
    if(str1.length() > str2.length())
    {
        cout << str1.length() << endl;
    }
    else if(str1.length() < str2.length())
    {
        cout << str2.length() << endl;
    }
    else{
        if(str1 == str2)
        {
            cout << -1 << endl;
        }
        else{
            cout << str1.length() << endl;
        }
    }

    return 0;
}

B. Mahmoud and a Triangle

题目链接
Mahmoud has n line segments, the i-th of them has length ai. Ehab challenged him to use exactly 3 line segments to form a non-degenerate triangle. Mahmoud doesn’t accept challenges unless he is sure he can win, so he asked you to tell him if he should accept the challenge. Given the lengths of the line segments, check if he can choose exactly 3 of them to form a non-degenerate triangle.

Mahmoud should use exactly 3 line segments, he can’t concatenate two line segments or change any length. A non-degenerate triangle is a triangle with positive area.

Input

The first line contains single integer n (3 ≤ n ≤ 105) — the number of line segments Mahmoud has.

The second line contains n integers a1, a2, …, an (1 ≤ ai ≤ 109) — the lengths of line segments Mahmoud has.

Output

In the only line print “YES” if he can choose exactly three line segments and form a non-degenerate triangle with them, and “NO” otherwise.

Examples

Input

5 1 5 3 2 4

Output

YES


Input

3 4 1 2

Output

NO

题意:
给出n个数,判断是否能从中找出三个数构成三角形。

思路:
将n个数从小到大排序,从头至尾遍历三个数,判断是否存在 a1+a2>a3

程序代码:

#include<iostream>
#include<algorithm>
using namespace std;
int array[100001];
int main()
{
    int n;
    int i, j;
    cin >> n;
    for(i=1; i<=n; i++)
    {
        cin >> array[i];
    }
    sort(array + 1, array + n + 1);

    for(i=1; i<=n-2; i++)
    {
        if(array[i] + array[i + 1] > array[i + 2])
        {
            cout << "YES\n";
            return 0;
        }

    }
    cout << "NO\n";

    return 0;
}

C. Mahmoud and a Message

题目链接
Mahmoud wrote a message s of length n. He wants to send it as a birthday present to his friend Moaz who likes strings. He wrote it on a magical paper but he was surprised because some characters disappeared while writing the string. That’s because this magical paper doesn’t allow character number i in the English alphabet to be written on it in a string of length more than ai. For example, if a1 = 2 he can’t write character ‘a’ on this paper in a string of length 3 or more. String “aa” is allowed while string “aaa” is not.

Mahmoud decided to split the message into some non-empty substrings so that he can write every substring on an independent magical paper and fulfill the condition. The sum of their lengths should be n and they shouldn’t overlap. For example, if a1 = 2 and he wants to send string “aaa”, he can split it into “a” and “aa” and use 2 magical papers, or into “a”, “a” and “a” and use 3 magical papers. He can’t split it into “aa” and “aa” because the sum of their lengths is greater than n. He can split the message into single string if it fulfills the conditions.

A substring of string s is a string that consists of some consecutive characters from string s, strings “ab”, “abc” and “b” are substrings of string “abc”, while strings “acb” and “ac” are not. Any string is a substring of itself.

While Mahmoud was thinking of how to split the message, Ehab told him that there are many ways to split it. After that Mahmoud asked you three questions:

How many ways are there to split the string into substrings such that every substring fulfills the condition of the magical paper, the sum of their lengths is n and they don't overlap? Compute the answer modulo 109 + 7.
What is the maximum length of a substring that can appear in some valid splitting?
What is the minimum number of substrings the message can be spit in? 

Two ways are considered different, if the sets of split positions differ. For example, splitting “aa|a” and “a|aa” are considered different splittings of message “aaa”.

Input

The first line contains an integer n (1 ≤ n ≤ 103) denoting the length of the message.

The second line contains the message s of length n that consists of lowercase English letters.

The third line contains 26 integers a1, a2, …, a26 (1 ≤ ax ≤ 103) — the maximum lengths of substring each letter can appear in.

Output

Print three lines.

In the first line print the number of ways to split the message into substrings and fulfill the conditions mentioned in the problem modulo 109  +  7.

In the second line print the length of the longest substring over all the ways.

In the third line print the minimum number of substrings over all the ways.

Examples

Input

3
aab
2 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Output

3
2
2


Input

10
abcdeabcde
5 5 5 5 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Output

401
4
3

题意:
一串小写字母组成的信息字符串,规定每个字母可以出现在子串中的最大子串长度,将信息分割成子串,问可以分割成的子串方法数,子串的最大长度,最小分割成的子串个数。

思路:
dp好题。

  1. dp1[i] 表示前i个字符可以分割成的子串方法数,枚举j从0~i-1,若 [j+1,i] 可以作为一个子串,则 dp1[i]+=dp[j]
  2. dp2[i] 表示前i个字符子串的最大长度,枚举j从0~i-1,若 [j+1,i] 可以作为一个子串,则 dp2[i]=max(dp[j],ij)
  3. dp3[i] 表示前i个字符最小分割成的子串个数,枚举j从0~i-1,若 [j+1,i] 可以作为一个子串,则 dp3[i]=min(dp3[j]+1)

时间复杂度 O(n3)

程序代码:

#include<iostream>
#include<string>
using namespace std;
const int mod = 1000000000 + 7;
int dp1[1001], dp2[1001], dp3[1001];
int len[27];        //每个字母能出现在子串中的最大子串长度 
int main()
{
    int n;
    string str;
    int i, j, k;
    cin >> n >> str;
    for(i=0; i<26; i++)
    {
        cin >> len[i];
    }

    dp1[0] = 1;
    dp2[0] = 0;
    dp3[0] = 0;
    dp1[1] = dp2[1] = dp3[1] = 1;
    for(i=2; i<=n; i++)
    {
        dp3[i] = dp3[i - 1] + 1;    //求最小前的预设值 
        for(j=0; j<i; j++)
        {
            bool pd = true;

            for(k=j+1; k<=i; k++)   //判断[j+1, i]的子串是否符合要求 
            {
                if(len[str[k-1] - 'a'] < i - j)
                {
                    pd = false;
                    break;
                }
            }

            if(pd){
                dp1[i] += dp1[j];
                dp1[i] %= mod;
                dp2[i] = max(dp2[i], dp2[j]);
                dp2[i] = max(dp2[i], i - j);
                dp3[i] = min(dp3[i], dp3[j] + 1);
            }
        }
    }

    cout << dp1[n] << endl << dp2[n] << endl << dp3[n] << endl;
    return 0;
}

算法改进:
以上的算法用了三重循环,时间复杂度较高,可以将第第二层的循环改为由i-1~0,这样逆序可以算出每次字串中字母要求值的最小值,省去了第三次循环,时间复杂度 O(n2) 具体看程序代码。

程序代码:

#include<iostream>
#include<string>
using namespace std;
const int mod = 1000000000 + 7;
int dp1[1001], dp2[1001], dp3[1001];
int len[27];
int main()
{
    int n;
    string str;
    int i, j, k;
    cin >> n >> str;
    for(i=0; i<26; i++)
    {
        cin >> len[i];
    }

    dp1[0] = 1;
    dp2[0] = 0;
    dp3[0] = 0;
    dp1[1] = dp2[1] = dp3[1] = 1;
    for(i=2; i<=n; i++)
    {
        dp3[i] = dp3[i - 1] + 1;
        int minn = 99999;
        for(j=i-1; j>=0; j--)
        {
            minn = min(minn, len[str[j]-'a']);

            if(minn >= i - j){
                dp1[i] += dp1[j];
                dp1[i] %= mod;
                dp2[i] = max(dp2[i], dp2[j]);
                dp2[i] = max(dp2[i], i - j);
                dp3[i] = min(dp3[i], dp3[j] + 1);
            }
        }
    }

    cout << dp1[n] << endl << dp2[n] << endl << dp3[n] << endl;
    return 0;
}

D. Mahmoud and a Dictionary

题目链接
Mahmoud wants to write a new dictionary that contains n words and relations between them. There are two types of relations: synonymy (i. e. the two words mean the same) and antonymy (i. e. the two words mean the opposite). From time to time he discovers a new relation between two words.

He know that if two words have a relation between them, then each of them has relations with the words that has relations with the other. For example, if like means love and love is the opposite of hate, then like is also the opposite of hate. One more example: if love is the opposite of hate and hate is the opposite of like, then love means like, and so on.

Sometimes Mahmoud discovers a wrong relation. A wrong relation is a relation that makes two words equal and opposite at the same time. For example if he knows that love means like and like is the opposite of hate, and then he figures out that hate means like, the last relation is absolutely wrong because it makes hate and like opposite and have the same meaning at the same time.

After Mahmoud figured out many relations, he was worried that some of them were wrong so that they will make other relations also wrong, so he decided to tell every relation he figured out to his coder friend Ehab and for every relation he wanted to know is it correct or wrong, basing on the previously discovered relations. If it is wrong he ignores it, and doesn’t check with following relations.

After adding all relations, Mahmoud asked Ehab about relations between some words based on the information he had given to him. Ehab is busy making a Codeforces round so he asked you for help.

Input

The first line of input contains three integers n, m and q (2 ≤ n ≤ 105, 1 ≤ m, q ≤ 105) where n is the number of words in the dictionary, m is the number of relations Mahmoud figured out and q is the number of questions Mahmoud asked after telling all relations.

The second line contains n distinct words a1, a2, …, an consisting of small English letters with length not exceeding 20, which are the words in the dictionary.

Then m lines follow, each of them contains an integer t (1 ≤ t ≤ 2) followed by two different words xi and yi which has appeared in the dictionary words. If t = 1, that means xi has a synonymy relation with yi, otherwise xi has an antonymy relation with yi.

Then q lines follow, each of them contains two different words which has appeared in the dictionary. That are the pairs of words Mahmoud wants to know the relation between basing on the relations he had discovered.

All words in input contain only lowercase English letters and their lengths don’t exceed 20 characters. In all relations and in all questions the two words are different.

Output

First, print m lines, one per each relation. If some relation is wrong (makes two words opposite and have the same meaning at the same time) you should print “NO” (without quotes) and ignore it, otherwise print “YES” (without quotes).

After that print q lines, one per each question. If the two words have the same meaning, output 1. If they are opposites, output 2. If there is no relation between them, output 3.

See the samples for better understanding.

Examples

Input

3 3 4
hate love like
1 love like
2 love hate
1 hate like
love like
love hate
like hate
hate like

Output

YES
YES
NO
1
2
2
2


Input

8 6 5
hi welcome hello ihateyou goaway dog cat rat
1 hi welcome
1 ihateyou goaway
2 hello ihateyou
2 hi goaway
2 hi hello
1 hi hello
dog cat
dog hi
hi hello
ihateyou goaway
welcome ihateyou

Output

YES
YES
YES
YES
NO
YES
3
3
1
1
2

题意:
给出m对字符串和每两个之间的关系,关系分为相同和相反两种,可传递,判断给出的关系是否和之前的关系相矛盾,矛盾则忽略这条,最后判断q组字符串的关系。

思路:
种类并查集,每次记录自己和父亲的距离,用距离的奇偶反映关系的种类,相同则为偶数,相反则为奇数,合并时注意调整距离,具体见代码,若两个节点有共同的父亲,则存在关系,通过与父亲距离相减的奇偶情况判断关系种类。

程序代码:

#include<iostream>
#include<map>
#include<cmath>
#include<string>
using namespace std;
map<string, int> ids;
int fa[100001];
int rela[100001];

int getF(int x)
{
    if(fa[x] != x){
        int f = fa[x];
        fa[x] = getF(fa[x]);
        rela[x] += rela[f];
        return fa[x];
    }   
    else{
        return x;
    }
}

int merge(int z, int x, int y)
{
    int fx = getF(x);
    int fy = getF(y);
    if(fx != fy)
    {
        fa[fx] = fy;
        rela[fx] = z + rela[y] - rela[x];
        cout << "YES\n";
    }
    else{
        z = (z==2?0:z);
        if(abs(rela[x] - rela[y]) % 2 == z)
        {
            cout << "YES\n";
        }
        else{
            cout << "NO\n";
        }
    }
}

int main()
{
    int n, m, q;
    int i, j, k;
    cin >> n >> m >> q;

    for(i=1; i<=n; i++)
    {
        string str;
        cin >> str;
        fa[i] = i;
        ids[str] = i;
    }   

    for(i=1; i<=m; i++)
    {
        int x;
        string str1, str2;
        cin >> x >> str1 >> str2;
        if(x == 1){
            merge(2, ids[str1], ids[str2]);
        }
        else{
            merge(1, ids[str1], ids[str2]);
        }
    }

    for(i=1; i<=q; i++)
    {
        string str1, str2;
        cin >> str1 >> str2;
        int x = ids[str1];
        int y = ids[str2];
        int fx = getF(x);
        int fy = getF(y);

        int type;
        if(fx == fy){
            cout << abs(rela[x] - rela[y]) % 2 + 1 << endl;
        }
        else{
            cout << 3 << endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_27008079/article/details/55051564