A
题意:给我们最长木块的边长,木块的高永远是1,木块的长是i/2向上取整。问我们用这些木块拼成正方形的最大边长。
思路:我们通过计算可以发现连续两个可以拼成相同长度的正方形。偶数的话直接除2.奇数的话就可以除以2再加1.
#include <cstring>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
void solve()
{
long long n;
cin >> n;
if (n % 2 == 1)
{
cout << n / 2 + 1 << endl;
}
else
{
cout << n / 2 << endl;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
B
题意:给一个定义就是如果一个字符串内,每个字符出现的数量都小于不同的字符的个数的话,这个串就会被称为一个优秀字符串。然后给我们一个字符串,问我们有几个优秀字符子串。
思路:这个题的话有1e6的数据所以暴力肯定是不行的,我们可以想到一个字符串如果超过100个字符的话,那么它肯定不会是优秀的字符串,因为不同的字符一共就10个那么最多就是每个不同的字符出现10次,如果再出现的话就肯定是不符合要求的 。我们边遍历边求值就可以,如果记下来统一处理的话,就会出现大约 O ( n 3 ) O(n^3) O(n3)的复杂度,就肯定过不了。具体细节详见代码。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
int ans = 0;
for (int i = 0; i < n; i++)
{
string ss = "";
unordered_map<char, int> st;
unordered_map<char, int> mp;
int butong = 0;
int Max = 0;
for (int j = i; j < n && j - i + 1 <= 100; j++)//如果串的长度超过100的话直接退出循环
{
if (st[s[j]] == false)
{
st[s[j]] = true;
butong++; //记不同的个数
}
mp[s[j]]++;
Max = max(Max, mp[s[j]]);//找出这个子串里出现的最多的字符
if (Max <= butong) //满足条件的话答案就加一
ans++;
}
}
cout << ans << "\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
}
return 0;
}
C
题意:给我们一个数组我们可以把一个值为0的数改为任何数。我们定义从 a 1 + a 2 + . . . + a i = 0 a_1+a_2+...+a_i = 0 a1+a2+...+ai=0的一个i为一个贡献,问我们通过无限次改变我们能得到的最大的贡献是多少。
思路:
我们可以把0作为分割,两个0之间看做一段,一个0可以影响后面的贡献,我们只把左边的0算到这一段里,右边的算到下一段里。
我们可以从后往前枚举,如果碰到一个0的话,我们就看看这一段里哪个前缀和出现次数最多,我们就加上这个前缀和出现的次数,这样的贡献肯定是最大的。
当是最左边的那一段的时候它只有右边有0,左边没有0,那么只有前缀和为0的时候才能对答案有贡献,所以我们只需要在最后加上前缀和是0的次数就可以了。
注:用unordered_map会T,map就可以,可能是建表太慢了,不如红黑树快。每查到一个0,就要重新建一次。
前缀和数组记得开long long 不然会RE
#include <iostream>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
#define endl "\n"
const int N = 1e6 + 10;
int a[N];
long long sum[N];
void solve()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
map<long long, int> mp;
int Max = 0;
int ans = 0;
for (int i = n; i >= 1; i--)
{
mp[sum[i]]++;
Max = max(Max, mp[sum[i]]);
if (a[i] == 0)
{
ans += Max;
mp.clear();
Max = 0;
}
}
if (mp[0])
ans += mp[0];
printf("%d\n", ans);
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}