第一题:4491.数组操作
分析:该题就是需要进行一个计算最后一个元素的前缀和和所有前缀和中最小前缀和,然后相减的操作。可以用sort函数对前缀和数组中的元素进行排序,最小前缀和也就是排序后的p[0]。
代码:
#include
#include
using namespace std;
const int N = 110;
int n;
int q[N],p[N];
int main(){
int s,x;
cin >> n;
for(int i = 1;i <= n;i ++)scanf("%d",&q[i]);
for(int i = 1;i <= n;i ++ )p[i] = p[i - 1] + q[i];
s = p[n];
sort(p,p + n + 1);
x = p[0];
cout << s - x << endl;
return 0;
}
第二题:4492.减法操作
分析:如果n为偶数,那么n的最小质因子必定是2,需要进行减法操作的次数就是;如果n为奇数,那么n的最小质因子p必定也是奇数,n - p就为偶数,于是这时一共需要进行
次操作即可。可用试除法求最小质因子。
代码:
#include
#include
#include
using namespace std;
typedef long long LL;
int main()
{
LL n;
cin >> n;
LL res = 0;
if(n % 2){
for(int i = 2;i <= n / i;i ++ )
if(n % i == 0){
n -= i;
res ++;
break;
}
if(n % 2)res ++,n = 0;
}
res += n / 2;
cout << res << endl;
return 0;
}
第二题:2332.坐上公交的最晚时间
分析:我们只需找到最后一个上车的乘客,然后往前找空位即可,因为最后一个乘客能上车,代表前面的乘客都能顺利上车,我们只需以上帝视角找位置插队,利用双指针模拟上车过程,思路参考。
代码:
class Solution {
public:
int latestTimeCatchTheBus(vector& buses, vector& passengers, int capacity) {
int n = buses.size(), m = passengers.size();
sort(buses.begin(), buses.end());
set P;
for (int x : passengers) P.insert(x);
int ans = 1, cnt = 0;
auto it = P.begin();
for (int i = 0; i < n; i++) {
while (cnt < capacity && it != P.end() && *it <= buses[i]) {
// 乘客上车,抢先在它之前上车
// 由于 set 是有序的,如果存在 t - 1 时刻到达的乘客,那么一定是上一个乘客
if (it == P.begin() || *prev(it) != *it - 1) ans = *it - 1;
it++; cnt++;
}
// 公交没有坐满,准备发车
if (cnt < capacity && P.count(buses[i]) == 0) ans = buses[i];
cnt = 0;
}
return ans;
}
};
第三题:2333.最小差值平方和
分析:由于要计算的是,所以对第一个数组进行减一的操作可以等同于对第二个数组进行加一的操作,即可以将
看作一个新数组的第i项,计算出差值绝对值,用一个数组arr[]存储绝对值,总操作次数为
,验证可得减去数值较大的数对结果影响较大。思路参考
代码:
using ll = long long;
class Solution {
public:
long long minSumSquareDiff(vector& nums1, vector& nums2, int k1, int k2) {
vector vec(1e5 + 1, 0);
int n = nums1.size();
for (int i = 0; i < n; i++) vec[abs(nums1[i] - nums2[i])]++;
int k = k1 + k2;
for (int i = vec.size() - 1; k > 0 && i > 0; i--) {
int change = min(k, vec[i]);
vec[i - 1] += change;
k -= change;
vec[i] -= change;
}
ll ans = 0;
for (ll i = 0; i < vec.size(); i++) {
if (vec[i] != 0) {
ans += i * i * vec[i];
}
}
return ans;
}
};
第一题:2335.装杯子需要的最短总时长
分析:将饮料按数量大小排序,从小到大依次是x,y,z。要尽量匹配两种不同的饮料,我们可以分为两种情况讨论。①当时,将z与x或y交叉分配用时是最短的,此时总时长就是z。②当
时,若z为偶数可以先将超出z的部分的x和y匹配直到x+y=z再让z与x或y交叉分配;若z为奇数,最后就剩下一杯无法匹配。思路参考
代码:
class Solution {
public:
int fillCups(vector& amount) {
sort(amount.begin(), amount.end());
if (amount[0] + amount[1] <= amount[2]) return amount[2];
else {
int time = amount[0] + amount[1] - amount[2];
return (time + 1) / 2 + amount[2];
}
}
};
第三题:2337.移动片段得到字符串
分析:首先分析题目,找出两个字符串身上的性质:①删除“_”后的start和target中L和R的数量和排序都是一一对应的②未删除“_”时start中的L只能在target中对应的第某个“L”的右边,这样才能通过左移达到想要的结果。同理R也是,只能在target中对应R的左边,这样才能通过右移得到。
代码:
class Solution {
public:
bool canChange(string start, string target) {
int n = start.size();
//定义两个数组分别用来表示删除“_”后的的start和target数组
vector s;
vector t;
for(int i = 0; i < n; i ++){
if(start[i] != '_')s.push_back(start[i]);//s.push_back(i):在s数组后加入元素start[i]
if(target[i] != '_')t.push_back(target[i]);
}
if(s != t)return false;
for(int i = 0,j = 0;i < n;i ++){
if(start[i] == '_')continue;
while(target[j] == '_')j ++;
if(start[i] == 'L' && i < j)return false;
if(start[i] == 'R' && i > j)return false;
j ++;
}
return true;
}
};