【Codeforces】766 - 个人总结

题目链接
A. Mahmoud and Longest Uncommon Subsequence
思维题。当且仅当a==b时输出“-1”,不然输出a,b中最长的那个。
可以这么理解,如果a,b不相等,假设strlen(a)>=strlen(b),那我将a作为一个串去和b比较,一定是不同字串。

B. Mahmoud and a Triangle
英语不好,那个非退化三角形其实就是普通的三角形,退化三角形就是两短边之和等于第三边,也就是一条线段。
sort一下,相邻的比较一下就可以了。

C. Mahmoud and a Message
DP题。DP太差,看的大佬代码。
对于第一问,我们用DP[i]表示前i位的方法数,那么可以得到状态转移方程:

D P [ i ] = j = 1 i D P [ j 1 ]

以为你总可以把从[j,i]这一段分在一起,那么方法数就只由前j位决定,就是DP[j]。
第二问用一个变量存一下就好,长度就是i-j+1的最大值。
第三问,其实和第一个DP有着异曲同工之处,我们总是能将[j,i]这段分成一段,那么分成子串数只由前j位决定,就是DP2[j]。状态转移方程:
D P 2 [ i ] = m i n ( D P [ 0 ] , D P 2 [ 1 ] , . . . D P 2 [ i 1 ] ) + 1

用一个lim表示当前子串必须小于的长度即可。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 2e3;
const int mod = 1e9+7;
int n, dp[N], dp2[N], a[N];
char s[N];

int main(int argc, char const *argv[])
{
    scanf("%d %s", &n, s+1);
    for(int i = 0; i < 26; ++i) scanf("%d", &a[i]);
    dp[0] = 1;
    int mmax = 0;
    for(int i = 1; i <= n; ++i){
        int lim = n;
        dp2[i] = i;
        for(int j = i; j >= 1; --j){
            lim = min(lim, a[s[j]-'a']);
            if(i - j + 1 > lim) break;  
            dp[i] = (dp[i] + dp[j - 1]) % mod;
            dp2[i] = min(dp2[i], dp2[j - 1] + 1);
            mmax = max(mmax, i-j+1);
        }
    }
    printf("%d\n%d\n%d\n", dp[n], mmax, dp2[n]);
    return 0;
}

D:
给出n个单词,m次操作,q次查询。
操作有两种,一种是两种为同义词,另一种是 两种为反义词。
如果操作不与之前形成的关系冲突,输出YES,否则输出NO。
查询:给两个单词求它们的关系,同义词输出1,反义词输入2。

用0表示与根节点同义,1表示反义。

重要的还是find函数,在刚经过merge后,并查集的结构可能不是一颗只有两层的树,但是下一步无论是查询还是操作都有一步find,这样会把并查集的结构变成一颗最多只有两层的树,星形的,并且更新了每个节点与根节点的关系。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5;
int n, m, q, val[N], pre[N];
map<string ,int > dic;
string word;
int find(int x);
void merge(int d, int x, int y);
int main(int argc, char const *argv[])
{
    cin >> n >> m >> q;
    for(int i = 1; i <= n; ++i){
        cin >> word;
        dic[word] = i;
        val[i] = 0;
        pre[i] = i;
    }
    int d;
    string x, y;
    while(m--){
        cin >> d >> x >> y;
        merge(d, dic[x], dic[y]);
    }
    while(q--){
        cin >> x >> y;
        int fx = find(dic[x]);
        int fy = find(dic[y]);
        if(fx == fy)    printf("%d\n", 1 + (val[dic[x]] != val[dic[y]]));
        else puts("3");
    }
    return 0;
}

int find(int x){
    if(pre[x] == x) return x;
    int tem = find(pre[x]);
    val[x] = (val[x] + val[pre[x]]) % 2;
    return pre[x] = tem;
}

void merge(int d, int x, int y){
    int fx = find(x);
    int fy = find(y);
    if(fx == fy){
        if(d == 1 && val[x] == val[y])  puts("YES");
        else if(d == 2 && val[x] != val[y]) puts("YES");
        else puts("NO");
    } else {
        val[fy] = (val[x] + val[y] + d - 1) % 2;
        pre[fy] = fx;
        puts("YES");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41009682/article/details/82426562
今日推荐