Codeforces Round #618 (Div.2)

比赛链接 / 官方题解链接

A. Non-zero

Solution

是 $0$ 的数必须加 $1$,否则乘积为 $0$;此后若和非零,则不用操作,否则操作数加一(任取一个非零数加一,由于和为零,能够保证存在至少一个正数,对其操作后乘积仍然非零)

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

int T, n, a;

int main(){
read(T);
while(T--){
read(n);
int ans = 0, sum = 0;
for(int i = 1; i <= n; i++){
read(a);
if(a == 0) a++, ans++;
sum += a;
}
printf("%d\n", ans + (sum == 0));
}
return 0;
}

B. Assigning to Classes

Solution

容易知道,尽量平均分最好,也就是说,若 $n$ 为奇数,就分成 $n:n$ 的两份;若 $n$ 为偶数,就分成 $n-1:n+1$ 的两份。先排序,则无论是哪种情形,两中位数都是 $a_n$ 和 $a_{n+1}$.

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<algorithm>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 200005;

int T, n;
LL a[N];

int main(){
read(T);
while(T--){
read(n);
for(int i = 1; i <= 2 * n; i++) read(a[i]);
sort(a+1, a+2*n+1);
printf("%lld\n", a[n+1] - a[n]);
}
return 0;
}

C. Anu Has a Function

Solution

首先需要发现:$f(a,b)=(a|b)-b=a\&(\sim b)$,故 $f(f(\cdots f(f(a_1,a_2),a_3),\cdots a_{n-1})a_n)=a_1\&(\sim a_2)\&(\sim a_3)\&\cdots\&(\sim a_n)$. 其值与谁放在开头作为 $a_1$ 有关,剩余元素随意放即可。于是枚举放在开头的元素,计算它 $AND$ 上其他元素取反后的$AND$,后者可以通过预处理前后缀求得。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 100005;

int n, mark;
LL a[N], pre[N], sub[N], maxx = -1;

int main(){
read(n);
pre[0] = sub[n+1] = (1ll << 33) - 1;
for(int i = 1; i <= n; i++){
read(a[i]);
pre[i] = pre[i-1] & (~a[i]);
}
for(int i = n; i >= 1; i--){
sub[i] = sub[i+1] & (~a[i]);
LL res = a[i] & sub[i+1] & pre[i-1];
if(maxx < res){
mark = i;
maxx = res;
}
}
printf("%lld ", a[mark]);
for(int i = 1; i <= n; i++){
if(i == mark) continue;
printf("%lld ", a[i]);
}
putchar(10);
return 0;
}

D. Aerodynamic

Solution

手玩一些多边形后可以发现,$P$ 对边平行且相等(即中心对称)即可。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<algorithm>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 100005;

int n;
struct Point{
LL x, y;
}p[N];
typedef Point Vector;
Point operator - (Point A, Point B){ return (Point){A.x - B.x, A.y - B.y}; }
LL operator ^ (Vector A, Vector B){ return A.x * B.y - A.y * B.x; } // cross product
LL Length2(Vector A){ return (A.x * A.x + A.y * A.y); }

int main(){
read(n);
for(int i = 1; i <= n; i++) read(p[i].x, p[i].y);
if(n & 1){
puts("NO");
return 0;
}
else{
for(int i = 1; i <= n / 2; i++){
int j = i + n / 2;
int nxti = i + 1, nxtj = j + 1;
if(nxtj == n + 1) nxtj = 1;
Vector v1 = p[nxti] - p[i], v2 = p[nxtj] - p[j];
if((v1 ^ v2) != 0 || Length2(v1) != Length2(v2)){
puts("NO");
exit(0);
}
}
}
puts("YES");
return 0;
}

E. Water Balance

Solution

【参考官方题解】对于前缀和序列 $\{sum_i\}$,题设操作对应为:选择一段区间 $[l,r]$,并将其中的数 $sum_i(l\leq i\leq r)$ 更改为

这个式子实际上是 $(l-1,sum_{l-1}),(r,sum_r)$ 两点确定的直线上横坐标为 $i$ 的点的纵坐标。把所有点 $(i,sum_i)$ 画在坐标系中,发现求得下凸包即可。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<algorithm>
#include<cstdio>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;

const int N = 1000005;

int n, ch[N];
LL a[N];
double s[N];

void getConvexHull(){
for(int i = 0; i <= n; i++){
while(ch[0] > 1 &&
(double)(a[ch[ch[0]]] - a[ch[ch[0]-1]]) / (ch[ch[0]] - ch[ch[0]-1]) >
(double)(a[i] - a[ch[ch[0]]]) / (i - ch[ch[0]]))
ch[0]--;
ch[++ch[0]] = i;
}
}

int main(){
read(n);
for(int i = 1; i <= n; i++) read(a[i]), a[i] += a[i-1];
getConvexHull();
int pt = 2;
for(int i = 1; i <= n; i++){
while(i > ch[pt]) pt++;
s[i] = (double)(a[ch[pt]] - a[ch[pt-1]]) / (ch[pt] - ch[pt-1]) * (i - ch[pt-1]) + a[ch[pt-1]];
}
for(int i = 1; i <= n; i++)
printf("%.9f\n", s[i] - s[i-1]);
return 0;
}
作者

xyfJASON

发布于

2020-02-10

更新于

2020-12-20

许可协议

评论