E. Three Strings
题目大意:给你3个字符串a,b,c,每次取a或b的首字符添加到新字符的末尾,让你求出c与新字符最少有多少个字符不同
思路:经典的字符串匹配的动态规划题,f[i][j]表示a的前i个字符和b的前j个字符中与c的前(i+j)个字符最大匹配数,转移方程:f[i+1][j] = max(f[i][j]+(a[i] == c[i+j]) ), f[i][j+1] = max(f[i][j] + (b[j] == c[i+j]) f[0][0] = 0, 注意边界
代码:
void solve()
{
string a,b,c;
cin >> a >> b >> c;
int n = a.size(), m = b.size();
vector<vector<int>> f(n+1,vector<int>(m+1,-1e9));
f[0][0] = 0;
for (int i = 0; i <= n; i ++ )
for (int j = 0; j <= m; j ++ )
{
if (i + 1 <= n) f[i+1][j] = max(f[i+1][j],f[i][j] + (a[i] == c[i+j]));
if (j + 1 <= m) f[i][j+1] = max(f[i][j+1],f[i][j] + (b[j] == c[i+j]));
}
cout<<n+m-f[n][m]<<endl;
}
链接:Problem - 2050E - Codeforces
E. Sakurako, Kosuke, and the Permutation
题目大意:给你一个排列,问你操作几次元素交换,能将这个排列变为简单排列,简单排列的定义为
如果每个 ii (1≤i≤n)(1≤i≤n) 中都有一个,那么排列 pp 就被认为是简单的。 (1≤i≤n)(1≤i≤n) 都成立,那么这个排列 pp 就是简单排列:
- pi=ipi=i
- ppi=i
思路:找环,每次把环中元素数减1除2加到答案上去
代码:
void solve()
{
int n; cin >> n;
vector<int> p(n+1),st(n+1);
for (int i = 1; i <= n; i ++ ) cin >> p[i];
int ans = 0;
for (int i = 1; i <= n; i ++ )
{
st[i] = 1;
int cnt = 1, x = i;
while (!st[p[x]] && p[x] != x)
{
cnt ++ ;
st[p[x]] = 1;
x = p[x];
}
ans += (cnt - 1)/2;
}
cout<<ans<<endl;
}
链接:Problem - 2033E - Codeforces
C. Two Movies
题目大意:有两个数组,你每次可以从这两个数组中任取一个数加到该数组对应的和中,最后叫你求最大的(这两个和中的较小的那一个)
#1 因为元素中只有0,-1,1,所以当这两个数组在某点时不相等时,取较大的那个就行
#2 相等的情况则要令判
思路:我们可以离线操作,先不算相等的情况,把相等的情况记录下来,最后根据两个合来判断取拿个,当都为-1时,合较大的那个取,为1时,合较小的那个取
代码:
void solve()
{
int n; cin >> n;
vector<array<int,2>> v(n);
int ans1 = 0, ans2 = 0;
for (int i = 0; i < n; i ++ ) cin >> v[i][0];
for (int i = 0; i < n; i ++ ) cin >> v[i][1];
vector<int> op;
for (int i = 0; i < n; i ++ )
{
if (v[i][0] > v[i][1]) ans1 += v[i][0];
else if (v[i][0] < v[i][1]) ans2 += v[i][1];
else op.push_back(v[i][0]);
}
for (auto t : op)
{
if (t == 1)
{
if (ans1 >= ans2) ans2 ++ ;
else ans1 ++ ;
}
else if (t == -1)
{
if (ans1 >= ans2) ans1 -- ;
else ans2 -- ;
}
}
cout<<min(ans1,ans2)<<endl;
}
链接:Problem - 1989C - Codeforces
C. Set Construction
题目大意:给你一个二进制方阵,让你根据该位置0,1的情况来构造n个不同的集合
#1 思考如何构造
思路:先给每个排列设置一个不同的初始值,如果i包含于j,就将i的初始值放进j中,对于a包含于b,a包含于c,b包含于c的情况,是否应该将b的改变值放进c呢,不需要,因为b包含于c时,必有a也包含于c
代码:
void solve()
{
int n; cin >> n;
vector<string> g(n+1);
for (int i = 1; i <= n; i ++ )
{
cin >> g[i];
g[i] = ' ' + g[i];
}
set<int> s[n+1];
for (int i = 1; i <= n; i ++ )
s[i].insert(i);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
{
if (g[i][j] == '1') s[j].insert(i);
}
for (int i = 1; i <= n; i ++ )
{
cout<<s[i].size()<<" ";
for (auto it = s[i].begin(); it != s[i].end(); it++)
cout<<*it<<" ";
cout<<endl;
}
}