A. Yet Another String Game
按照题意模拟即可。
B. The Great Hero
除了最后一击(hero可以只剩很少的血量),其他的伤害都需要老老实实互换。因此贪心的选择攻击力最大的怪兽放到最后打即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
struct node
{
int a, b;
bool operator<(const node temp) const
{
return a < temp.a;
}
} s[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
long long A, B, n;
cin >> A >> B >> n;
for (int i = 1; i <= n; i++)
cin >> s[i].a;
for (int i = 1; i <= n; i++)
cin >> s[i].b;
sort(s + 1, s + 1 + n);
bool flag = 1;
for (int i = 1; i <= n; i++)
{
long long num = s[i].b / A + (s[i].b % A ? 1 : 0);
if (s[i].a * (num - 1) >= B)
flag = 0;
else
B -= s[i].a * num;
}
cout << (flag ? "YES" : "NO") << endl;
}
return 0;
}
C. Searching Local Minimum
CF交互经典二分。
特判一下corner, 二分出mid之后,查询mid-1,mid,mid+1,三个值的相对大小有以下几种情况:
- 123。令r=mid-1,因为有1<2 ,那么在mid的左侧一定存在一个解。
- 132。令r=mid-1,因为有1<3 ,那么在mid的左侧一定存在一个解。
- 213。直接输出mid。
- 312。直接输出mid。
- 321。令l=mid+1,因为有1<2 ,那么在mid的右侧一定存在一个解。
- 231。令l=mid+1,因为有1<3 ,那么在mid的右侧一定存在一个解。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
if (n == 1)
{
cout << "! " << 1 << endl;
return 0;
}
else if (n == 2)
{
cout << "? " << 1 << endl;
cout.flush();
cin >> a[1];
cout << "? " << 2 << endl;
cin >> a[2];
cout.flush();
cout << "! " << (a[1] < a[2] ? 1 : 2) << endl;
cout.flush();
return 0;
}
cout << "? " << 1 << endl;
cout.flush();
cin >> a[1];
cout << "? " << 2 << endl;
cout.flush();
cin >> a[2];
if (a[1] < a[2])
{
cout << "! " << 1 << endl;
return 0;
}
cout << "? " << n << endl;
cout.flush();
cin >> a[n];
cout << "? " << n - 1 << endl;
cout.flush();
cin >> a[n - 1];
if (a[n] < a[n - 1])
{
cout << "! " << n << endl;
return 0;
}
int l = 2, r = n - 1;
while (l <= r)
{
int mid = l + r >> 1, res1, res2, res3;
cout << "? " << mid - 1 << endl;
cout.flush();
cin >> res1;
cout << "? " << mid << endl;
cout.flush();
cin >> res2;
cout << "? " << mid + 1 << endl;
cout.flush();
cin >> res3;
if (res2 < res1 && res2 < res3)
{
cout << "! " << mid << endl;
cout.flush();
return 0;
}
if (res1 < res2)
r = mid - 1;
else
l = mid + 1;
}
return 0;
}
D1. Painting the Array I
贪心。
显然,当前考虑的元素
a
i
a_i
ai只和之前已经分成的两个数组的最后一个元素有关。
记数组
1
1
1的最后一个元素为
V
1
V1
V1。
记数组
2
2
2的最后一个元素为
V
2
V2
V2。
考虑 a i a_i ai时,若
- V 1 = V 2 = a i V1=V2=a_i V1=V2=ai,那么 a i a_i ai压入哪个数组都一样。
- V 1 = a i V1=a_i V1=ai, a i a_i ai需要压入数组 2 2 2。这样做肯定不会比压入数组 1 1 1更劣,如果将 a i a_i ai压入数组 1 1 1,当前就会立即失去一个贡献,反之,只是“可能在未来”会失去一个贡献。
- V 2 = a i V2=a_i V2=ai,同上, a i a_i ai需要压入数组 1 1 1。
- V 2 ≠ a i V2 \neq a_i V2=ai 且 V 1 ≠ a i V1\neq a_i V1=ai,在当前看, a i a_i ai压入哪个数组都一样,这时候就可以考虑能不能使“未来”的贡献更大(也即使用 a i a_i ai增加一个贡献),显然只有当 a i + 1 a_{i+1} ai+1 等于 V 1 V1 V1或 V 2 V2 V2时,可以用 a i {a_i} ai隔开他们来增加(避免减少)一个贡献。
最后对两数组计算贡献即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
vector<int> v1, v2;
v1.emplace_back(-1);
v2.emplace_back(-1);
a[n + 1] = -1;
for (int i = 1; i <= n; i++)
{
if (a[i] != v1.back() && a[i] != v2.back())
{
if (v1.back() == a[i + 1])
v1.emplace_back(a[i]);
else
v2.emplace_back(a[i]);
}
else if (a[i] != v1.back())
v1.emplace_back(a[i]);
else
v2.emplace_back(a[i]);
}
int ans = 0, pre = -1;
for (auto it : v1)
{
if (it == pre)
continue;
else
ans++, pre = it;
}
pre = -1;
for (auto it : v2)
{
if (it == pre)
continue;
else
ans++, pre = it;
}
cout << ans << endl;
return 0;
}
D2. Painting the Array II
两个题虽然背景差不多,但是贪心的方向还有略有不同。
同D1,我们
记数组
1
1
1的最后一个元素为
V
1
V1
V1。
记数组
2
2
2的最后一个元素为
V
2
V2
V2。
考虑 a i a_i ai时,若
- V 1 = V 2 = a i V1=V2=a_i V1=V2=ai,那么 a i a_i ai压入哪个数组都一样。
- V 1 = a i V1=a_i V1=ai, a i a_i ai显然需要压入数组 1 1 1。
- V 2 = a i V2=a_i V2=ai, a i a_i ai显然需要压入数组 2 2 2。
- V 2 ≠ a i V2 \neq a_i V2=ai 且 V 1 ≠ a i V1\neq a_i V1=ai,在当前看, a i a_i ai压入哪个数组都一样,这时候就可以考虑能不能用 a i a_i ai使“未来”的贡献更小,不同于D1,这里需要考虑的“未来”包含的元素不仅仅是 a i + 1 a_{i+1} ai+1,而是后面的所有元素。我们考虑,在 a i a_i ai之后,更快出现的是 V 1 V1 V1还是 V 2 V2 V2,如果是 V 1 V1 V1,那么就将 a i a_i ai压入数组 2 2 2,避免 a i a_i ai隔开两个相同的数,反之亦然。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
int a[N];
map<int, deque<int>> mp;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
mp[a[i]].push_back(i);
for (int i = 1; i <= n + 1; i++)
mp[i].push_back(0x3f3f3f3f);
//压入一个无穷,表示后面该数不会再出现
vector<int> v1, v2;
v1.emplace_back(-1);
v2.emplace_back(-1);
mp[-1].push_back(0x3f3f3f3f);
for (int i = 1; i <= n; i++)
{
if (a[i] != v1.back() && a[i] != v2.back())
{
if (mp[v1.back()].front() < mp[v2.back()].front())
v2.emplace_back(a[i]);
else
v1.emplace_back(a[i]);
}
else if (a[i] == v1.back())
v1.emplace_back(a[i]);
else
v2.emplace_back(a[i]);
mp[a[i]].pop_front();
}
int ans = 0, pre = -1;
for (auto it : v1)
{
if (it == pre)
continue;
else
ans++, pre = it;
}
pre = -1;
for (auto it : v2)
{
if (it == pre)
continue;
else
ans++, pre = it;
}
cout << ans << endl;
return 0;
}
211

被折叠的 条评论
为什么被折叠?



