A - Yet Another String Game
Problem 1480A - Yet Another String Game
Alice和Bob在玩回合制游戏,Alice先手。每次操作可以使得给定字符串任意一个位置字符变成任意一个字符(小写字符),已修改过的位置不能再改,如果所有位置都被修改则游戏结束。Alice目的是使得最终字符串字典序尽可能小,Bob反之。
Solution
签到题,因为字典序要最小,所以每次修改的位置都尽可能的靠前,就变成了Alice和Bob依次修改。
Code
#include <bits/stdc++.h> using namespace std; const int maxn = 5e5 + 10; char ans[maxn]; void solve() { scanf("%s", ans); int n = strlen(ans); for (int i = 0; i < n; ++ i) { if(i%2 == 0) { if(ans[i] == 'a') ans[i] = 'b'; else ans[i] = 'a'; } else { if(ans[i] == 'z') ans[i] = 'y'; else ans[i] = 'z'; } } printf("%s ", ans); } int main() { int t; scanf("%d", &t); while (t--) { solve(); } return 0; }
B - The Great Hero
Problem 1480B - The Great Hero
Hero的攻击力 A,血量 B。i-th monster 攻击力 ai,血量bi。Hero每次攻击一个monster双方都会损失对方攻击力等值血量。任何一个生命HP<=0时死亡。问Hero能否杀死所有的monster。即使在最后一击时同归于尽。
Solution
签到题。唔,当时做的时候是觉得攻击力最高的放最后打,后来看到了聚聚们的题解,发现全打一遍,然后依次判断每一只放到最后打是否可以获胜,比我场上的解法会更容易证明。
Code
#include <bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1e5 + 10; char ans[maxn]; struct Moster { ll a, b, daijia; } moster[maxn]; bool cmp(Moster x, Moster y) { if(x.a == y.a) return x.b < y.b; return x.a < y.a; } void solve() { ll A, B, n; scanf("%lld %lld %lld", &A, &B, &n); for (int i = 1; i <= n; ++ i) scanf("%lld", &moster[i].a); for (int i = 1; i <= n; ++ i) { scanf("%lld", &moster[i].b); } sort(moster + 1, moster + 1 + n, cmp); for (int i = 1; i <= n; ++ i) { ll t1 = (moster[i].b + A - 1) / A; ll t2 = (B + moster[i].a - 1) / moster[i].a; if(t2 > t1) B -= t1 * moster[i].a; else if(t1 == t2) { if(i == n) { printf("YES "); return; } printf("NO "); return; } else { printf("NO "); return; } } printf("YES "); } int main() { int t; scanf("%d", &t); while (t--) { solve(); } return 0; }
C. Searching Local Minimum
Problem 1479A - Searching Local Minimum
交互题。给定一个全排列,你一共可以进行不超过100次询问,每次询问可以询问一个下标并得到对应位置上的值。输出这个序列中任意一个局部最小数。局部最小数的定义为i-th的值比(i+1)-th的值和(i-1)-th的值都小。0-th和(n+1)-th上的值定义为+∞。
Solution
如果我们把值都二维坐标轴上,那么我们会得到若干条首尾相连的直线,那么我们的目的就是找到其中一个任意两条k1*k2<0且相连直线的交点(这样的点一定存在,因为数组两端值都为+∞)。那么我们每次去二分i-th和(i+1)-th上的值,如果前者小于后者那么在i-th左侧一定存在答案,反之在右侧。(画图易证)
Code
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int a[maxn]; int n; void ff() { fflush(stdout); } int ask(int x) { printf("? %d ",x); ff(); int temp; scanf("%d", &temp); return temp; } void out(int x) { printf("! %d ",x); ff(); exit(0); } void check(int x) { if(a[x] == 0) a[x] = ask(x); if(a[x+1] == 0) a[x + 1] = ask(x + 1); if(a[x-1] == 0) a[x - 1] = ask(x - 1); if (a[x] < a[x + 1] && a[x] < a[x - 1]) { out(x); } } int main() { scanf("%d", &n); a[0] = a[n + 1] = n + 1; check(1); check(n); int l = 1, r = n - 1; int ans = 0; while (l <= r) { int mid = l + r >> 1; check(mid); if(a[mid]<a[mid+1]) r = mid - 1; else l = mid + 1; } }
D1 - Painting the Array I
Problem 1479B1 - Painting the Array I
给定一个序列a,需要分成a1,a2两个序列,每个数只能被分到一个序列中,且同意序列中的数相对位置不变。定义seg(a)为将序列中相邻值相等的数合并后序列剩下的数。求max(seg(a1)+seg(a2))
Solution
贪心。易得,我们只需要考虑两个序列最后一个数字即可。设 ll 为a0序列最后一个元素,rr 为a1序列最后一个元素。
ll 和 rr 和当前值 i-th 有四种关系
- 其中一个与 i-th相等,另一个不等,那么肯定将当前值移到不相等的序列最优
- 两个数都与 i-th相等,那么随便移
- 两个数都与 i-th不相等,那么就需要考虑 (i+1)-th这个数与 ll 和 rr 的关系了
- 如果 ll 与 (i+1)-th相等,那么就将当前的 i-th移到 ll 所在序列,这样就可能避免后面 (i+1)-th只能选择一个导致 (i+2)-th本能做出贡献但是无效的情况
- 反之亦然,如果都相等或者都不相等就无所谓了
Code
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int n; int arr[maxn]; int main() { scanf("%d", &n); for (int i = 1; i <= n; ++ i) { scanf("%d", arr + i); } int sum = 1; int ll = arr[1], rr = -1; for (int i = 2; i <= n; ++ i) { if(arr[i] == ll && arr[i] != rr) { rr = arr[i]; sum++; } else if(arr[i] != ll && arr[i] == rr) { ll == arr[i]; sum++; } else if(arr[i] != ll && arr[i] != rr) { if(i+1 <= n && arr[i+1] == rr) { rr = arr[i]; sum++; } else { ll = arr[i]; sum++; } } } printf("%d ", sum); return 0; }
D2 - Painting the Array II
Problem 1479B2 - Painting the Array II
给定一个序列a,需要分成a1,a2两个序列,每个数只能被分到一个序列中,且同意序列中的数相对位置不变。定义seg(a)为将序列中相邻值相等的数合并后序列剩下的数。求min(seg(a1)+seg(a2))
Solution
待补
Code
E - Continuous City
Problem 1479C - Continuous City
Solution
待补
Code