Educational Codeforces Round 2
Educational Codeforces Round 2
https://codeforces.com/contest/600
3/6: ABD
A. Extract Numbers
小模拟。把一个字符分成两部分输出,遇到 ';' 或 ',' 视为单词分隔符,非负整数的单词在第一行输出,单词与单词之间要输出一个','。要注意空单词也要输出逗号。
分析:对于判断第一类单词其实也很容易,如果出现了非数字字符,就一定不属于第一类;如果是一个有前导0的数字也不属于第一类。至于空单词的处理:塞一个 $ 符号进去,输出的时候特判就好。
把细节考虑清楚之后就很容易了,一遍过还是很开心的ovo
#include <bits/stdc++.h>
using namespace std;
bool check (string s) {
//出现非数字字符
for (int i = 0; i < s.size (); i++) {
if (!isdigit (s[i])) return false;
}
if (s[0] == '0' && s.size () != 1) return false;
return true;
}
void print (vector <string> v) {
int n = v.size ();
cout << "\"";
if (v[0] != "$") cout << v[0];
for (int i = 1; i < n; i++) {
cout << ",";
if (v[i] != "$") cout << v[i];
}
cout << "\"" << endl;
}
int main () {
string s;
cin >> s;
vector <string> v1, v2;
string t;
s += ';';
for (int i = 0; i < s.size (); i++) {
if (s[i] == ';' || s[i] == ',') {
if (t.empty ()) v2.push_back ("$");
else {
//cout << t << endl;
if (check (t)) v1.push_back (t);
else v2.push_back (t);
t = "";
}
}
else t += s[i];
}
if (v1.empty ()) cout << "-\n";
else print (v1);
if (v2.empty ()) cout << "-\n";
else print (v2);
}
//没有前导0的非负数
B. Queries about less or equal elements
题意:输出a数组中不大于当前输入数字的个数
分析:对a排序后二分即可
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, a[N];
int main () {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
sort (a + 1, a + n + 1);
for (int j = 1; j <= m; j++) {
int x; cin >> x;
int pos = upper_bound (a + 1, a + n + 1, x) - a;
cout << pos - 1 << ' ';
}
//cout << (int)(log (2e5) * (2e5));
}
C. Make Palindrome
题意:每次可以改变任意一个字符(消耗代价1),或者重排列各字符(不用消耗代价),输出最少操作次数下,拥有最小字典序的回文串。
分析:直接贪心的变。记录原串中字符出现的次数,如果为偶数,就不用变,均匀分布在两边即可,如果为奇数,就改变一个,经量减少其大小。所以先对字符串进行一次排序,然后分奇偶次数处理。
特别注意的是,奇数长度的字符串中,可以保留最中间的一个(字符出现次数为奇数)。
具体实现看代码:
#include <bits/stdc++.h>
using namespace std;
int main () {
string s;
cin >> s;
int n = s.size ();
sort (s.begin (), s.end ());
//cout << s << endl;
map<char, int> mp;
for (auto i : s) mp[i] ++;
char find; //最中间的奇可以保留
vector <char> odd;
for (char i = 'a'; i <= 'z'; i++) {
if (mp[i] & 1) odd.push_back (i);
}
//for (auto i : odd) cout << i << ' '; cout << endl;
for (int i = 0, j = odd.size() - 1; i < j; i++, j--) {
//odd[i] <- odd[j]
mp[odd[i]] ++, mp[odd[j]] --;
}
// for (char i = 'a'; i <= 'z'; i++) {
// if (mp[i]) cout << i << ": " << mp[i] << endl;
// }
for (char i = 'a'; i <= 'z'; i++) {
if (mp[i] & 1) find = i;
if (mp[i] < 2) continue;
int cnt = mp[i];
for (int j = 0; j < cnt / 2; j++) cout << i;
}
if (n & 1) cout << find;
for (char i = 'z'; i >= 'a'; i--) {
if (mp[i] < 2) continue;
int cnt = mp[i];
for (int j = 0; j < cnt / 2; j++) cout << i;
}
}
//最小操作做次数下的最小字典序
//把奇偶分开试试
D. Area of Two Circles' Intersection
简单计算几何。求两个圆的面积并。
分析如图:
相交:
\(S\) = \(S_{扇ACD}-S_{△ACD}+S_{扇BCD}-S_{△BCD}\)
然后通过余弦公式计算两夹角 \(∠CAD,∠CBD\)
利用扇形面积公式和三角形面积公式就可以求得了,这两个公式就不做过多赘述具体可以看代码。
包含:面积并为较小的圆的面积
注意细节:
输入的坐标和半径在参与运算时会爆 \(int\),所以要开 \(long\,\,double\)
\(double\) 精度不够,要开 \(long \,\,double\)。
#include <bits/stdc++.h>
#define PI acos(-1)
#define double long double
using namespace std;
struct circle {
double x, y, r;
};
double dis(circle a, circle b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int main() {
cout << fixed << setprecision (7);
circle a, b;
cin >> a.x >> a.y >> a.r;
cin >> b.x >> b.y >> b.r;
double len = dis(a, b);
if (len + min(a.r, b.r) <= max(a.r, b.r)) {
if (a.r < b.r) cout << PI * a.r * a.r << endl;
else cout << PI * b.r * b.r << endl;
}
else if (len >= a.r + b.r) cout << "0.0000000";
else {
double d1 = 2 * acos((a.r * a.r + len * len - b.r * b.r) / (2 * a.r * len));
double d2 = 2 * acos((b.r * b.r + len * len - a.r * a.r) / (2 * b.r * len));
double area1 = d1 * a.r * a.r / 2 - a.r * a.r * sin(d1) / 2;
double area2 = d2 * b.r * b.r / 2 - b.r * b.r * sin(d2) / 2;
cout << area1 + area2 << endl;
}
}
//扇形面积 α * r * r / 2
//小心爆int
//用long double
E. Lomsat gelral
题解完善中...
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5;
int h[N], e[N * 2], ne[N * 2], idx;
int a[N], sz[N], son[N], n;
int ans[N], cnt[N], maxn, sum;
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs1 (int u, int fa) {
sz[u] = 1;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue;
dfs1 (j, u);
sz[u] += sz[j];
if (sz[j] > sz[son[u]]) son[u] = j;
}
}
void change (int u, int fa, int val, int sson) {
int color = a[u];
cnt[color] += val;
if (cnt[color] > maxn) maxn = cnt[color], sum = color;
else if (cnt[color] == maxn) sum += color;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa || j == sson) continue;
change (j, u, val, sson);
}
}
void dfs (int u, int fa, int sson) { //最后搜重
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa || j == son[u]) continue;
dfs (j, u, 0);
}
if (son[u]) dfs (son[u], u, 1);
change (u, fa, 1, son[u]); //清空父
ans[u] = sum;
if (sson == 0) {
change (u, fa, -1, 0);
sum = 0, maxn = 0; //轻儿子要清空
}
}
signed main () {
memset (h, -1, sizeof h);
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
add (x, y), add (y, x);
}
dfs1 (1, -1);
dfs (1, -1, -1);
for (int i = 1; i <= n; i++) cout << ans[i] << ' ';
}
//先算轻儿子,最后重儿子
//保留重儿子在cnt[]