Codeforces Round 944 (Div. 4)
A. My First Sorting Problem
思路:久违的比大小
AC code:
void solve() {
int x, y; cin>> x >> y;
cout << min(x, y) << " " << max(x, y) << endl;
}
B. Different String
题意:给出一个字符串,是否能重排成新的字符串并输出新字符串;
思路:排序后比一遍,倒序后再比一遍;
AC code:
void solve() {
string s; cin >> s;
string t = s;
sort(t.begin(), t.end());
if (t != s) {
cout << "YES" << endl;
cout << t << endl;
return;
}
reverse(t.begin(), t.end());
if (t != s) {
cout << "YES" << endl;
cout << t << endl;
return;
}
cout <<"NO" << endl;
}
C. Clock and Strings
题意:在圆形时钟上选择ab,cd四个点分别连线,看是否相交;
思路:看这四个点是不是交叉顺序排列的即可;
AC code:
bool check (int a, int b, int c, int d) {
if (a > b) swap(a, b);
if (c > d) swap(c, d);
return (a < c && c < b && b < d) || (c < a && a < d && d < b);
}
void solve() {
int a, b, c, d;
cin >> a >> b >> c >> d;
if (check(a, b, c, d) || check(c, d, a, b)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
D. Binary Cut
题意:将当前01字符串最少分割成多少个连续子串可以重新排列成字典序最小字符串;
思路:最多存在一个同时存在0和1的子串,可以将所有串分割成连续的0和1的子串,若存在至少一个01串,则答案-1即可;
AC code:
void solve() {
string s; cin >> s;
int ans = 0;
int cnt = 0, pos = 0;
for (int i = 1; i < s.size(); i ++) {
if (s[i] != s[i - 1]) cnt ++;
if (s[i] == '1' && s[i - 1] == '0') pos = 1;
}
ans = cnt;
if (pos) ans --;
cout << ans+1 << endl;
}
E. Find the Car
题意:
有0到n个站点,汽车从站点0开始行驶,已知汽车到达其中k个站点的时间,这k个站点之间的平均速度是相同的,即a1点到a2点为一个
平均速度,a2到a3点又是一个平均速度,不一定相同,不一定不同。
现在给出q个查询,每次查询0到n的其中一个点,询问到达该点的时间为多少。
思路:
二分查询时第一个大于当前查询点的l点,当前点的时间即为l-1点的时间 + l-1到l之间经过点的和;
注意,double会损失精度,在求单独一段时,用整型元素先乘后除才能减少精度损失,即:
所求距离 * l-1到l的总距离 / l-1到l的时间
AC code:
void solve() {
int n, k, q; cin >> n >> k >> q;
a[0] = 0, b[0] = 0;
for (int i = 1; i <= k; i ++) cin >> a[i];
for (int i = 1; i <= k; i ++) cin >> b[i];
while (q --) {
int d; cin >> d;
int l = 1, r = k;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] > d) r = mid;
else l = mid + 1;
}
if (n == d) {
cout << b[k] << ' ';
continue;
}
int ans = b[l - 1];
ans += ((d - a[l - 1]) * (b[l] - b[l - 1]) / (a[l] - a[l - 1]));
cout << ans << ' ';
} cout << endl;
}
F. Circle Perimeter
题意:略,题面描述非常简洁;
思路:直接俩for暴力枚举r一定超时,所以我们先枚举x坐标,对于y坐标,我们只枚举大于r的最小y坐标到小于r+1的最大y坐标即可;
在坐标轴上的点贡献为2,其他的贡献为4;
AC code:
void solve() {
int r; cin >> r;
int cnt = 0;
int r2 = r * r, rp = (r + 1) * (r + 1);
for (int i = 0; i <= r + 1; i ++) {
int x = i * i;
int mn = (int)ceil(sqrt((double)max(0LL, r2 - x)));
int mx = (int)floor(sqrt((double)(rp - 1 - x)));
for (int y = mn; y <= mx; y ++) {
if (x == 0 || y == 0) cnt += 2;
else cnt += 4;
}
}
cout << cnt << endl;
}
G. XOUR
题意:在n个非负整数的序列a中,可以任意交换两两异或值小于4的元素,求可能的最小字典序数组;
思路:可以发现,二进制下第一和第二位00,01,10,11的任何排列组合都是符合条件的,所以可以交换的元素除了首位和次位的二进制一定是相等的,我们存储这样相同的元素进行排列,按顺序输出即可;
这里很巧妙是可以用到map<int, priority_queue<int, vector, greater>> mp;来直接实现存储,排序,输出的目的;
存储过程中无需按位取,按x>>2进行存储即可;
AC code:
void solve() {
int n; cin >> n;
vector<int> a(n);
map<int, priority_queue<int, vector<int>, greater<int>>> mp;
for (int i = 0; i < n; i ++) {
int x; cin >> x;
a[i] = x;
mp[a[i] >> 2].push(x);
}
for (int i = 0; i < n; i ++) {
cout << mp[a[i] >> 2].top() << ' ';
mp[a[i] >> 2].pop();
} cout << endl;
}