A.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
string s;
cin >> s;
int current = 1;
int ans = 0;
for (auto k : s)
{
int t = k - '0';
if (t == 0)
{
t = 10;
}
ans += abs(t - current) + 1;
current = t;
}
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;
}
B.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
int n, k;
cin >> n >> k;
string s;
cin >> s;
map<char, int> mp;
for (auto t : s)
{
mp[t]++;
}
int p = n - k;
// cout << p << endl;
// cout << mp['a'] << endl;
for (auto [x, y] : mp)
{
if (p == 0)
{
break;
}
if (y % 2 == 0)
{
p -= min(p, y);
}
else
{
if (p % 2 == 0)
{
p -= min(p, (y - 1));
}
else
{
p -= min(p, y);
}
}
// cout << p << endl;
}
if (p == 0)
{
cout << "YES" << endl;
}
else
{
cout << "NO\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
int n, k;
cin >> n >> k;
vector<int> a(n);
int ans = -1;
int flag = 0;
int ou = 0;
int f3 = 0;
// vector<int> b(6,0);
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (a[i] % 2 == 0)
{
ou++;
}
if (a[i] % 4 == 3)
{
f3++;
}
if (a[i] % k == 0)
{
ans = 0;
}
flag = max(a[i] % k, flag);
}
if (ans == 0)
{
cout << 0 << endl;
return;
}
if (k == 2)
{
cout << 1 << endl;
return;
}
else if (k == 4)
{
// cout << ou << " " << f3 << "*"
// << " ";
int q = 2;
if (ou >= 2)
{
cout << 0 << endl;
return;
}
else
{
q -= ou;
if (f3 >= 1 || q == 1)
{
cout << 1 << endl;
}
else
{
cout << 2 << endl;
}
return;
}
}
else
{
cout << k - flag << endl;
return;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D.
/*
multiset 是C++标准库中的关联容器之一,它存储一组按特定顺序排列的元素。在 multiset 中,begin()、end()、rbegin() 和 rend() 分别是四个用于访问容器中元素的迭代器和反向迭代器。下面详细解释它们之间的区别:
begin():
begin() 返回指向容器中第一个元素的正向迭代器。
使用 *begin() 可以获取第一个元素的值。
正向迭代器通常从容器的最小元素开始,因为 multiset 中元素是按照键的排序顺序排列的(升序)。
end():
end() 返回指向容器中超出最后一个元素的位置的正向迭代器。
注意,end() 并不指向最后一个元素,而是指向最后一个元素之后的位置,不能解引用它。
end() 常用于循环迭代容器元素,通常在循环中以 end() 作为终止条件。
rbegin():
rbegin() 返回指向容器中最后一个元素的反向迭代器。
使用 *rbegin() 可以获取最后一个元素的值。
反向迭代器通常从容器的最大元素开始,因为 multiset 中元素是按照键的排序顺序排列的(升序)。
rend():
rend() 返回指向容器中超出第一个元素的位置的反向迭代器。
注意,rend() 并不指向第一个元素之前的位置,而是指向第一个元素之前的位置,不能解引用它。
rend() 常用于反向循环迭代容器元素,通常在循环中以 rend() 作为终止条件。
需要注意的是,在 multiset 中,元素是按键的排序顺序排列的,因此 begin() 和 rbegin() 指向的是最小和最大的元素,而 end() 和 rend() 分别指向第一个元素之前和最后一个元素之后的位置。这些迭代器和反向迭代器非常有用,可以帮助你有效地遍历 multiset 中的元素。
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
int n;
cin >> n;
char c;
int l, r;
multiset<int> sts, ends;
for (int i = 0; i < n; i++)
{
cin >> c >> l >> r;
if (c == '+')
{
sts.insert(l);
ends.insert(r);
}
else
{
sts.erase(sts.find(l));
ends.erase(ends.find(r));
}
if (sts.size() && *ends.begin() < *sts.rbegin())
{
// 现在,我们需要判断是否存在一对不相交的线段。
// 如果存在,那么一定有一个线段的右端点小于另一个线段的左端点。因此,我们只需要判断 ends 中最小的元素是否小于 sts 中最大的元素即可。
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
// cin >> t;
t = 1;
while (t--)
{
solve();
}
return 0;
}
E.
/*
针对下面两种情况分别举个例子
1:如果a[i]>=a[i-1],这里说的是>=原来的a[i-1]
2.a[i]<a[i-1]
下标: 0 1 2
如: 16 5 15,那么当a[1]<a[0]时,a[1]*2^2=20才能满足a[1]>=a[0],即ans[1]=2,此时不用改变a[1]的值,看能不能根据a[1]要操作多少次来求出a[2]要操作多少次
现在a[2]>a[1],是不是只要/2来求出一个最小的a[2]满足a[2]>=a[1],此时a[2]也只需要操作ans[1]次?就能满足后面操作后的a[2]>=操作后的a[1]?,然后/2和*2是不是可以相互抵消,ans[2]=ans[1]-t,t为/2的次数
那么当(a[1]*2<=a[2])时,a[2]可以除以2来满足a[2]>=a[1]求出最小的满足a[2]>=a[1]的a[2]
再看下一个例子:
下标: 0 1 2
16 5 2 a[2]<a[1]那么只能通过*2来求出最小的满足a[2]>=a[1]的a[2],这里a[2]*2^2=8>=5成立,t=2,所以ans[2]=ans[1]+t
如果每次都是while(a[i]<a[i-1])a[i]*=2;这样不仅可能会爆2^n范围,时间复杂度也很高
*/
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<long long> a(n), ans(n); // ans[i]表示满足a[i]>=a[i-1]的最小操作次数
for (int i = 0; i < n; i++)
{
cin >> a[i];
ans[i] = 0;
}
long long cnt = 0;
for (int i = 1; i < n; i++)
{
int b = a[i - 1], c = a[i];
if (b <= c)
{
int t = 0;
while (b * 2 <= c)
{
t++;
b *= 2;
}
ans[i] = max(0LL, ans[i - 1] - t);
}
else
{
int t = 0;
while (c < b)
{
c *= 2;
t++;
}
ans[i] = ans[i - 1] + t;
}
}
for (int i = 0; i < n; i++)
{
cnt += ans[i];
}
cout << cnt << "\n";
}
return 0;
}
G1.
/*
算法逻辑:
按题目要求有m=a[1]=1,求数组a,b至少要分别删除k个整数,保证数组a,b排列后满足a[i]<b[i]恒成立
给个样例解释:
数组a:1 1 1 2 2 3 3 4
数组b:1 1 1 1 3 3 3 3
排序后如果要满足a[i]<b[i]恒成立,观察可以知道假如a的最大值比b的最小值还要小,那么是不是不用删一定就可以存在这样的排列,
如果说b的最大值比a的最小值还要小,那么就不存在a[i]<b[i],就需要全部删完
回到一般情况,应该删掉哪些数呢?如果a数组中有一个数a[j]>所有的b[i]那么就找不到一个数b[i]>a[j]成立,a[j]必须删除,那么b数组里面该删哪个呢?
是不是有b[j]的值越小,在a中找到一个值a[i]满足a[i]<b[j]的机率就越小,把这个几率小的删除就好了
所以每次二分删掉a数组的后mid个和b数组前mid个,删除之后两数组依旧分别有序,如果b数组的较小者比a数组的较小者都小,那么就不满足所有的a[i]<b[i]了,继续更新mid
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
int n, m;
const int N = 1e5 + 5;
ll a[N], b[N];
bool check(int mid)
{
int reserve = n - mid; // 表示剩下的数,删掉a数组的后mid个和b数组前mid个
for (int i = 0; i < reserve; i++)
{
if (a[i] >= b[i + mid])
{
return false; // 表示一定不会满足
}
}
return true;
}
void solve()
{
cin >> n >> m;
// vector<ll> value,num;
a[0] = 1;
for (int i = 1; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
sort(a, a + n);
sort(b, b + n);
int l = 0, r = n;
while (l < r)
{
int mid = (l + r) / 2; // 如果数组a,b都删掉mid个数,判断之后的数组是否合法
if (check(mid))
{
// 可能删的数mid还能更少
r = mid;
}
else
{
l = mid + 1;
}
}
cout << l << "\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
法二、双指针寻找最多删多少组
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> a(n), b(n);
for (int i = 1; i < n; i++) {
std::cin >> a[i];
}
for (int i = 0; i < n; i++) {
std::cin >> b[i];
}
a[0] = 1;
std::sort(a.begin(), a.end());
std::sort(b.begin(), b.end());
int ans = 0;
for (int i = 0, j = 0; i < n; i++) {
while (j < n && a[i] >= b[j]) {
j++;
}
ans = std::max(ans, j - i);
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}