题目链接
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位的方法数,那么可以得到状态转移方程:
以为你总可以把从[j,i]这一段分在一起,那么方法数就只由前j位决定,就是DP[j]。
第二问用一个变量存一下就好,长度就是i-j+1的最大值。
第三问,其实和第一个DP有着异曲同工之处,我们总是能将[j,i]这段分成一段,那么分成子串数只由前j位决定,就是DP2[j]。状态转移方程:
用一个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");
}
}