(恩。。。noip后第一场cf,被虐得好惨啊。
主要是T2打错了一个字母找了1h...
居然只降了1分我感到很欣慰。。)
额,言归正传qwq.
A. Greed
题目大意:有一些可乐和杯子,告诉你每瓶可乐的多少的杯子的容量,问能不能把所有可乐放到两个杯子里。
做法:大水题,不解释。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int a[N];
int main()
{
scanf("%d", &n); LL sum = 0;
for (int i = 1; i <= n; i ++){
int x; scanf("%d", &x);
sum += x;
}
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
sort(a+1, a+1+n);
if (sum <= a[n]+a[n-1]){
puts("YES");
} else {
puts("NO");
}
return 0;
}
B. Wrath
题目大意:有一些人排成一队,每个人会杀死他前面最多li个人,现在所有人同时开始杀人,问最后活着的有几个。
做法:把所有人杀的人看成一堆区间,然后按左端点排序,扫描一遍即可算出答案。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 1000010;
int n;
struct Node{
int l, r;
}a[N];
const bool cmp(const Node &x, const Node &y)
{
return x.l < y.l;
}
int main()
{
scanf("%d", &n); int m = 0;
for (int i = 1; i <= n; i ++){
int x; scanf("%d", &x);
if (!x || i == 1) continue;
a[++ m].l = max(1, i-x);
a[m].r = i-1;
} int cnt = n;
n = m; int ans = 0;
if (n == 0){
printf("%d\n", cnt);
return 0;
}
sort(a+1, a+1+n, cmp);
int l = a[1].l, r = a[1].r;
for (int i = 2; i <= n; i ++){
if (a[i].l > r){
ans += r-l+1;
l = a[i].l; r = a[i].r;
} else {
r = max(r, a[i].r);
}
}
ans += r-l+1;
printf("%d\n", cnt-ans);
return 0;
}
C. Pride
题目大意:有n个数字,每一次操作可以把相邻两个数中的一个变成这两个数的gcd,问最少几次把所有数变成1。
做法:首先如果数组中本来就有1,记1的个数为cnt1,那么肯定在n-cnt1步操作后就变成全1。
如果数组中本身没有1,那么一定需要有一个1,然后就可以在n-1步之后变成全1。
所以我们暴力枚举一下所有区间,计算一下答案即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 2010;
int n;
int a[N];
int main()
{
scanf("%d", &n); int cnt1 = 0;
for (int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
if (a[i] == 1) cnt1 ++;
}
if (cnt1 > 0){
printf("%d\n", n-cnt1);
return 0;
} int ans = 1e9;
for (int i = 1; i <= n; i ++){
int x = a[i];
for (int j = i+1; j <= n; j ++){
x = __gcd(x, a[j]);
if (x == 1){
ans = min(ans, j-i+n-1);
break;
}
}
}
if (ans == 1e9) puts("-1");
else printf("%d\n", ans);
return 0;
}
D. Gluttony
题目大意:给一个数组a,让你构造一个数组b(b中元素和a中元素相同),使得a和b所有前缀和不相同。
做法:考虑一个构造方案,就是说把a从小到大排序以后,b中每一个数都放a对应位置的数的比它小的第一个数。
感觉有一点绕- - 呃形象点就是说,把a中所有元素都往前挪了一步,然后最小那个变成了最大那个。
然后正确性应该是显然的。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i, x, y) for (int i = (x); i <= (y); i ++)
using namespace std;
const int N = 25;
int n;
int a[N], rk[N], b[N];
const bool cmp(const int x, const int y)
{
return a[x] < a[y];
}
int main()
{
scanf("%d", &n);
rep(i, 1, n){
scanf("%d", &a[i]);
rk[i] = i;
} sort(rk+1, rk+1+n, cmp);
rep(i, 1, n-1){
b[rk[i+1]] = a[rk[i]];
}
b[rk[1]] = a[rk[n]];
rep(i, 1, n) printf("%d ", b[i]);
return 0;
}
=========================================================================
总结:
比赛时通过A,B,C,Rank 950,rating -1。
主要问题:T2细节问题导致错了好几次,时间严重浪费。
然后T3一开始没有想到,是问了某大佬才做出的qwq。
唉。。争取下次涨点rating...qwq。