Codeforces Round 944 (Div.4)

5月10日 Codeforces 实战记录。(0 -> 656)

第一次Codeforces试水,AC数7/8
比赛跳转:Codeforces Round 944 (Div. 4)

题解

A. B. E.

随题意模拟即可,不做赘述。

C. Clock and Strings

题意:判断环中两连线是否相交

分析:先锁定一条连线,再判断另一条边的两端点是否在连线同侧。

完整代码:

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
#include<bits/stdc++.h>
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

int main(){
int t = read();
while(t--){
int a = read(), b = read(), c = read(), d = read();

int mn = min(a, b), mx = max(a, b);

bool flag1 = 0, flag2 = 0;

if(mn < c && c < mx) flag1 = 1;
if(mn < d && d < mx) flag2 = 1;

if(flag1 ^ flag2)
cout << "YES" << '\n';
else cout << "NO" << '\n';
}

return 0;
}

补充解法

官方题解给出了一种很美妙的解法,直接用字符串模拟了两条连线的相对方位:

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
#include<bits/stdc++.h>
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

int main(){
int t = read();
while(t--){
int a = read(), b = read(), c = read(), d = read();

string s;
for (int i = 1; i <= 12; i++) {
if (i == a || i == b) {s += "a";}
if (i == c || i == d) {s += "b";}
}

cout << (s == "abab" || s == "baba" ? "YES\n" : "NO\n");
}
return 0;
}

D. Binary Cut

题意:通过剪切01序列,使其成为升序。

分析:先将所有01序列拆分成仅含0或仅含1的序列,再至多合并一对形如 0..0 1..1 的序列,即出现 01cnt--

完整代码:

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
#include<bits/stdc++.h>
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

int main(){
int t = read();
while(t--){
string s; cin >> s;
int cnt = 0;
char last = ' ';
for(int i = 0; i < s.length(); i++){
if(s[i] != last){
cnt ++;
last = s[i];
}
}
for(int i = 0; i < s.length() - 1; i++){
if(s[i] == '0' && s[i + 1] == '1'){
cnt--;
break;
}
}
cout << cnt << '\n';
}

return 0;
}

F. Circle Perimeter

题意:找出距离原点距离在 [r, r + 1) 内的整点个数。

分析:简化为4 * (第一象限与x轴正半轴格点数)

搜索时,对x轴上每一个i ,最高点 up 满足 i * i + up * up < (r + 1) * (r + 1),最低点 down 满足 i * i + down * down >= r * r,化简后 O(1) 找出 up down ,计数 up - down + 1 个格点即可。

完整代码:

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
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

signed main() {
int t = read();
while (t--) {
int r = read();
int cnt = 0;

int le = r * r;
int ri = le + r + r + 1;

for (int i = 1; i <= r; i++) {
int up = ceil(sqrt((ri - i * i))) - 1, down = ceil(sqrt((le - i * i)));
cnt += up - down + 1;
}

cout << cnt * 4 << '\n';
}

return 0;
}

G. XOUR

题意:对二进制表示下,仅有最后两位不同的数记为一组,各组内排序。

实现:直接用map将除去后两位的值映射到优先队列自动排序即可。

完整代码:

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
#include<bits/stdc++.h>
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

void solve(){
int n = read();
vector<int> a(n);
map<int, priority_queue<int, vector<int>, greater<int>>>mp;
for(int i = 0; i < n; i++){
a[i] = read();
mp[a[i] >> 2].push(a[i]);
}
for(int i = 0; i < n; i++){
cout << mp[a[i] >> 2].top() << ' ';
mp[a[i] >> 2].pop();
}
cout << '\n';
}

int main(){
int t = read();
while(t--)
solve();
return 0;
}