刚从Java转学C++,各种不熟,时间限度内只做了三题,犯了很多初学者会犯的错误,疯狂查stl的用法。记录一下前三题,都不难。
A. Adjacent Replacements
真实签到题,如果按照题目说法去模拟铁tle,其实题都不用看,观察样例可知奇数不变,偶数减一输出即可。
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int n, in[1005];
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &in[i]);
}
for(int i = 0; i < n; i++) {
if(in[i] % 2 == 0){
in[i]--;
}
printf("%d", in[i]);
if(i < n - 1) {
printf(" ");
}
}
printf("\n");
return 0;
}
B. Polycarp’s Practice
题目很长很恶心,有点难看懂。题意是让你把一个数组分成k段,这k段的最大值相加要最大,special judege,答案不唯一。
其实就是求top k,然后扫一遍,见top k就分段。
第一步先求top k,然后用map存储。
一直记得数据结构老师说过求top k用堆的效率很优秀,所以这里选用优先队列。
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int n, k, in[2005];
scanf("%d%d", &n, &k);
priority_queue<int, vector<int>, less<int> > wait;
map<int, int> m;
for(int i = 1; i <= n; i++) {
scanf("%d", &in[i]);
wait.push(in[i]);
}
int sum = 0;
for(int i = 0; i < k; i++) {
int get = wait.top();
wait.pop();
m[get]++;
sum += get;
}
int pre = 0, cnt = 0;
printf("%d\n", sum);
for(int i = 1; i <= n ; i++) {
if(m[in[i]] > 0) {
if(cnt == k - 1) {
printf("%d\n", n - pre);
break;
}
printf("%d ", i - pre);
pre = i;
m[in[i]]--;
cnt++;
}
}
return 0;
}
C.cf炸了看不到题目.jpg
这题,不像是acm会出现的题,更像是学语言时课本后面会出的作业题。简化题目后(其实题目最后已经用几句话帮你简化好了)就是求数组一头一尾两部分能划分出的数值最大、保证相等的和是多少。头部是sum1,尾部是sum3。
拿一个头指针一个尾指针,小的那一方sum就前进指针,相等时更新答案,并且让两个指针同时前进即可。
有一点要注意的是要严防指针越界,并且sum要用long long,输出要用lld(难受,因为这个wa了两发,用Java从来不考虑输出问题)。
ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int n, in[200005];
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &in[i]);
}
ll sum1 = 0, sum3 = 0, ans;
int i = 0, j = n + 1;
while(i < j) {
if(sum1 == sum3) {
ans = sum1;
sum1 += in[++i];
sum3 += in[--j];
}
while(sum1 < sum3 && i < n) {
sum1 += in[++i];
}
while(sum3 < sum1 && j > 1) {
sum3 += in[--j];
}
}
printf("%lld\n", ans);
return 0;
}