A - 游游画U
题意:游游想让你画一个大小为 n 的 "U" ,你能帮帮她吗?
思路:找到' . ' 和 ' * '字符每行的规律发现他们中心对称
AC代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int main()
{
cin >> n;
for(int i = 1; i <= 4 * n - n; i ++)
{
for(int j = 1; j <= n; j ++)
{
cout << '*';
}
for(int k = n + 1; k <= 3 * n; k ++)
{
cout << '.';
}
for(int l = 3 * n + 1; l <= 4 * n; l ++)
{
cout << '*';
}
cout << endl;
}
for(int a = 1; a <= n; a ++)
{
for(int b = 1; b <= a; b ++)
{
cout << ".";
}
for(int c = a + 1; c <= a + n; c ++)
{
cout << '*';
}
for(int d = a + n + 1; d <= 4 * n / 2; d ++)
{
cout << '.';
}
for(int d = a + n + 1; d <= 4 * n / 2; d ++)
{
cout << '.';
}
for(int c = a + 1; c <= a + n; c ++)
{
cout << '*';
}
for(int b = 1; b <= a; b ++)
{
cout << ".";
}
cout << endl;
}
return 0;
}
B - 游游的数组染色
题意:
游游拿到了一个数组,其中一些数被染成红色,一些数被染成蓝色。
游游想知道,取两个不同颜色的数,且它们的数值相等,有多少种不同的取法?
我们定义,两种取法如果取的某个数在原数组的位置不同,则定义为不同的取法。
思路:因为n的最大取值为2e5,所以使用常规的两层for循环会TLE,n * n会大于1e9;所以考虑使用STL里面的map函数能将时间复杂度降为O(n),然后建立map,键:数字 值 :[first,second] first 代表'R' second代表'B'
AC代码:
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int N = 200010;
typedef long long LL;
int n, temp;
int a[N];
LL ans = 0;
string colors;
int main()
{
cin >> n;
for (int i = 0; i < n; i ++)
{
cin >> temp;
a[i] = temp;
}
cin >> colors;
map<int, pair<int, int>> mp;
for (int i = 0; i < n;i ++)
{
if(colors[i] == 'R')
{
mp[a[i]].first ++;
}
else
{
mp[a[i]].second ++;
}
}
for(auto& [k,v] : mp)
{
ans += v.first * v.second;
}
cout << ans;
return 0;
}
C - 游游的交换字符
题意:
游游拿到了一个01串(仅由字符'0'和字符'1'构成的字符串)。游游每次操作可以交换两个相邻的字符,例如,对于字符串"11001"而言,游游可以交换第二个字符和第三个字符变成"10101"。
游游希望最终字符串任意两个相邻的字符都不相同,她想知道最少需要多少操作次数?保证答案是有解的,即最终一定能形成任意两个相邻的字符都不相同的字符串。
思路:判断1
和0
的个数分别是odd
, ever
,如果abs(odd-ever) > 1
,那么一定不满足。(这个性质很重要,我一开始没注意到0和1的个数只能相差1或者相等)但是题目中说的是前提满足。因此无需判断,那么对字符串长度分为两种情况:
- 长度是偶数
10101010....
类型0101010....
类型
2、长度是奇数
101010101...
类型0101010...
类型
交换位置的时候,只需构造出上述可能的字符串,这里从第一位1
或0
以此遍历,然后让原来字符串对应位置和构造字符串的相对应位置的距离就是贡献。举个例子:
111000-->101010
,这里我们移动1
- 第一位
1
,下标为0
,对应构造串的下标为0
, 无需移动,贡献为0
- 第二位
1
,下标为1
,对应构造串的下标为2
, 贡献为2-1=1
- 第三位
1
,下标为2
,对应构造串的下标为4
, 贡献为4-2=2
所以需要移动3次即可,我们移动0
也是同理,两者是等价的。
AC代码:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
int main()
{
string s;
cin >> s;
LL n = s.size();
LL sum = 0;
for(int i = 0 ; i < n ; i ++ ) if(s[i] == '1') sum ++;
if(n & 1)
{
vector<int> a(n);
char c;
if(sum == n / 2 + 1) c = '1';
else c = '0';
int k = 0;
for(int i = 0 ; i < n ; i ++ )
if(s[i] == c) a[k ++ ] = i;
LL ans = 0;
for(int i = 0 ; i < k ; i ++ )
ans += abs(2 * i - a[i]);
cout << ans << endl;
}else
{
LL ans = 0 , res = 0;
vector<int> a(n);
int k = 0;
for(int i = 0 ; i < n ; i ++ ) if(s[i] == '1') a[k ++ ] = i;
for(int i = 0 ; i < k ; i ++ )
ans += abs(2 * i - a[i]);
for(int i = 0 ; i < k ; i ++ )
res += abs(2 * i + 1 - a[i]);
cout << min(res , ans);
}
return 0;
}