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\)
利用扇形面积公式和三角形面积公式就可以求得了,这两个公式就不做过多赘述具体可以看代码。
image
包含:面积并为较小的圆的面积
image

注意细节:
输入的坐标和半径在参与运算时会爆 \(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[]

F. Edge coloring of bipartite graph

posted @ 2022-12-16 15:41  Sakana~  阅读(26)  评论(1编辑  收藏  举报