1. Magnitude (Easy Version)


思路:
这里我们可以声明两个变量 l和r,从左向右遍历
1.如果l>=0,l就累加这个数
2.如果l<0,就让r加上这个数,此时如果r<0就让l加上这个r,r重新赋值为0,此时l仍然为负数
3.如果l<0,就让r加上这个数,此时如果r>0,保留r不变,继续往后遍历。
最后我们得到两种可能:
1.l>=0,r=0。这种情况下答案就是l
2.l<0 r>=0。这种情况下答案就是abs(l)+r
cpp
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<map>
#include<set>
#define int long long
using namespace std;
void solve() {
int n;
cin >> n;
vector<int>nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
int l = 0;
int r = 0;
for (int i = 0; i < n; i++) {
if (l >= 0) {
l += nums[i];
}
else if (l < 0) {
r += nums[i];
if (r < 0) {
l += r;
r = 0;
}
else if (r >= 0) {
continue;
}
}
}
if (l < 0) {
l = abs(l);
}
cout << l + r << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t; cin >> t;
while (t--)solve();
return 0;
}
2.Have Your Cake and Eat It Too




思路:
对给定的三个数组分别使用前缀和,枚举三人l和r的先后顺序(共六种)分别判断是否符合条件,若符合条件则输出。
代码:
cpp
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<map>
#include<set>
#define int long long
using namespace std;
int n;
int target;
typedef struct place {
int l;
int r;
}p;
bool deal_sum(vector<int>a, vector<int>b, vector<int>c,int num1,int num2,int num3) {
int i = 1;
while (a[i] < target) {
i++;
if (i == n-1) {
return false;
}
}
int marka = i;
while (b[i] - b[marka] < target) {
i++;
if (i == n)return false;
}
int markb = i;
if (c[n] - c[markb] < target) {
return false;
}
p x[4];
x[num1].l = 1;
x[num1].r = marka;
x[num2].l = marka + 1;
x[num2].r = markb;
x[num3].l = markb + 1;
x[num3].r = n;
for (int i = 1; i <= 3; i++) {
cout << x[i].l << ' ' << x[i].r << ' ';
}
cout << endl;
return true;
}
void solve() {
cin >> n;
vector<int>suma(n + 1);
vector<int>sumb(n + 1);
vector<int>sumc(n + 1);
for (int i = 1; i <= n; i++) {
int a; cin >> a;
suma[i] = suma[i - 1] + a;
}
if (suma[n] % 3 == 0) {
target = suma[n] / 3;
}
else {
target = suma[n] / 3 + 1;
}
for (int i = 1; i <= n; i++) {
int b; cin >> b;
sumb[i] = sumb[i - 1] + b;
}
for (int i = 1; i <= n; i++) {
int c; cin >> c;
sumc[i] = sumc[i - 1] + c;
}
if (deal_sum(suma, sumb, sumc,1,2,3))return;
if (deal_sum(suma, sumc, sumb,1,3,2))return;
if (deal_sum(sumb, suma, sumc,2,1,3))return;
if (deal_sum(sumb, sumc, suma,2,3,1))return;
if (deal_sum(sumc, suma, sumb,3,1,2))return;
if (deal_sum(sumc, sumb, suma,3,2,1))return;
cout << -1 << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t; cin >> t;
while (t--)solve();
return 0;
}
3.GCD-sequence



思路:
先算出原始的b数组(gcd之后的数组),然后从左向右遍历找出第一个b[i]>b[i+1]的位置i,这时出问题的值可能有三个a[i],a[i+1],a[i+2],依次去掉这三个值,获得去掉该值后的三个b数组,若三个数组存在一个非减数组,则输出"YES",如果不存在,输出"NO"。
代码:
cpp
#include<iostream>
#include<vector>
#include<algorithm>
#define int long long
using namespace std;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void solve() {
int n;
cin >> n;
vector<int>nums(n);
for (int i = 0; i < n; i++) {
cin >> nums[i];
}
if (n == 1) {
cout << "YES" << endl;
return;
}
vector<int>b(n - 1);
for (int i = 0; i < n - 1; i++) {
b[i] = gcd(nums[i], nums[i + 1]);
}
int mark = -1;
for (int i = 0; i < n - 2; i++) {
if (b[i] > b[i + 1]) {
mark = i;
break;
}
}
if (mark == -1) {
cout << "YES" << endl;
return;
}
for (int j = 0; j < 3; j++) {
int del_pos = mark + j;
if (del_pos >= n) break;
vector<int>temp;
for (int i = 0; i < n; i++) {
if (i != del_pos) {
temp.push_back(nums[i]);
}
}
vector<int>btemp(n - 2);
int flag = 0;
for (int i = 0; i < n - 2; i++) {
btemp[i] = gcd(temp[i], temp[i + 1]);
if (i > 0 && btemp[i - 1] > btemp[i]) {
flag = 1;
break;
}
}
if (flag == 0) {
cout << "YES" << endl;
return;
}
}
cout << "NO" << endl;
}
signed main() {
int t; cin >> t;
while (t--)solve();
return 0;
}
4.Final Boss


思路:
来自题解。利用set存入结构体pair,,结构体中的第一个变量代表第几个回合,第二个变量代表第几个技能,set首先按照结构体第一个变量大小排序,若第一个值大小相等,则按照第二个排序,具体思路见代码注释。
代码:
cpp
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
#define int long long
void solve() {
int h, n;
cin >> h >> n;
vector<int>a(n);
vector<int>c(n);
for (int i = 0; i < n; i++)cin >> a[i];
for (int i = 0; i < n; i++)cin >> c[i];
set<pair<int, int>>s;
for (int i = 0; i < n; i++) {
s.insert({ 1,i });
}//初始化s,在第一个回合里,所有技能均可使用
int turn = 1;//turn代表当前回合数
while (h > 0) {
turn = s.begin()->first;
int i = s.begin()->second;//这里从s中取出第一个元素,该元素在所有元素中turn最小
h -= a[i];//对boss造成伤害
s.insert({ turn + c[i],i });//下一次若想使用该技能需要在第turn+c[i]回合中
s.erase(*s.begin());//该技能在该回合使用完毕,可以删除。
}
cout << turn << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t; cin >> t;
while (t--)solve();
return 0;
}
5.Swap Dilemma



思路:
一步距离无论是多少的交换,都等同于奇数 次距离为2交换,这时假设a的数组不变,所以可以直接找把b数组交换为a数组时,一共需要多少步,不管这一步的距离是多少都是奇数次距离为2的交换,如果是偶数,则可以实现
为什么是偶数就可以实现?当总需求的 "等效次数" 为偶数时,能通过合理组合这些操作(或抵消多余步骤),实现数组的转换。
代码:
cpp
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#define int long long
using namespace std;
void solve() {
int n; cin >> n;
vector<int>a(n+1);
vector<int>b(n+1);
map<int, int>mp;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++) {
cin >> b[i];
mp[b[i]] = i;
}
int ans = 0;
for (int i = 1; i <= n; i++) {
if (b[i] == a[i]) {
continue;
}
if (mp[a[i]] == 0) {
cout << "NO" << endl;
return;
}
int x = mp[a[i]];
swap(b[i], b[x]);
mp[b[i]] = i;
mp[b[x]] = x;
ans++;
}
if (ans % 2 == 0) {
cout << "YES" << endl;
return;
}
cout << "NO" << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t; cin >> t;
while (t--)solve();
return 0;
}