AtCoder Beginner Contest 225(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 225(补题)相关的知识,希望对你有一定的参考价值。

D - Play Train

链接: link.

题意:

N N N个或者分离的火车头,现在有 Q Q Q次操作,每次操作有 3 3 3种类型, 1. x 1.x 1.x y y y代表把 x x x车的尾部和 y y y车的头部连接起来
2. x 2.x 2.x y y y代表把 x x x车的尾部和 y y y车的头部分离开
3. x 3.x 3.x代表 输出与 x x x车连接的所有车,输出个数并从头到尾输出各个车的编号

思路:

用非路径压缩版并查集就可以解决这个问题,直接按照输入的操作,分别实现并查集的合并、分离,并按照顺序输出并查集元素。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 10;
int fa[N];
int son[N];
int n, q;
int find(int x) 
    if (x != fa[x]) return find(fa[x]);
    return x;


void Union(int a, int b) 
    fa[b] = a;
    son[a] = b;


void del(int a, int b) 
    fa[b] = b;
    son[a] = a;


void print(int x) 
    int st = find(x);
    vector<int> res;
    while (son[st] != st) 
        res.push_back(st);
        st = son[st];
    
    res.push_back(st);
    cout << res.size() << " ";
    for (int i = 0; i < res.size(); i++) 
        cout << res[i] << " ";
    
    puts("");

int main() 
    cin >> n >> q;
    for (int i = 0; i < N; i++) 
        fa[i] = i;
        son[i] = i;
    
    while (q--) 
        int op, x, y;
        scanf("%d%d", &op, &x);
        if (op == 1) 
            scanf("%d", &y);
            Union(x, y);
        
        if (op == 2) 
            scanf("%d", &y);
            del(x, y);
        
        if (op == 3) 
            print(x);
        
    

E - 7

链接: link.

题意:

在二维坐标轴中,给 N N N个坐标,在二维坐标系中有 N N N 7 7 7, 7 7 7是由坐标 ( x i , y i ) (x_i,y_i) (xi,yi) ( x i − 1 , y i ) (x_i-1,y_i) (xi1,yi)构成的线段和 ( x i , y i ) (x_i,y_i) (xi,yi) ( x i , y i − 1 ) (x_i,y_i-1) (xi,yi1)g构成的线段组成,如果一个 7 7 7与坐标原点形成的四边形,与其他的四边形没有发生冲突(即没有交点),就说明 7 7 7是好的,现在问有多少个好 7 7 7

思路:

对于一个 ( x i , y i ) (x_i,y_i) (xi,yi)考虑与 ( x i − 1 , y i ) (x_i-1,y_i) (xi1,yi) ( x i , y i − 1 ) (x_i,y_i-1) (xi,yi1)构成的图形,就是以 ( x i − 1 , y i ) (x_i-1,y_i) (xi1,yi) ( x i , y i − 1 ) (x_i,y_i-1) (xi,yi1)和原点所形成的两条直线所占据的图形,这两条直线的斜率为 k 1 和 k 2 k1和k2 k1k2。如果某条直线与当前这个图形的两条直线有交点,那就说明这条直线的斜率在 [ k 1 , k 2 ] [k1,k2] [k1,k2]之间。所以说每个 7 7 7所占有的斜率 [ k 1 , k 2 ] [k1,k2] [k1,k2],可以看作在数轴上占据了这段这段区间,现在问题转换为最大不相交区间个数(不包括端点)
也可以通过极角排序来实现,一样的原理。
注:因精度问题不开long double 过不了

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;

int main() 
    int n;
    cin >> n;
    vector<pair<long double, long double> > s(n);
    for (int i = 0; i < n; i++) 
        ld x, y;
        cin >> x >> y;
        s[i].second = atan2(y - 1, x);
        s[i].first = atan2(y, x - 1);
    

    sort(s.begin(), s.end());

    ld now = 0.0;
    ll res = 0;

    for (int i = 0; i < n; i++) 
        if (now <= s[i].second) 
            res++;
            now = s[i].first;
        
    
    cout << res << endl;

F - String Cards

链接: link.

题意:

给定 N N N个字符串,现在让你选出 K K K个字符串,可以以任意顺序拼接,现在让你输出拼接后字典序最小的字符串。

思路:

如果此题没有选 K K K个字符串的限制,而是任意拼接然后输出字典序最小,题目就会变成下面这道题
题目链接: link.
链接: link
在没有限制的情况下,就只需要对字符串拼接后的大小来进行排序。即

bool cmp(string a, string b)  return a + b < b + a; 

含义就是排序的后面的子串不管是什么样只要往前连,肯定使连起来的字符串变小,说白了 就是两个字符串 a b ab ab b a ba ba排序,要是 a b ab ab b a ba ba a a a就放 b b b左边。此时排完序后,定义一个 d p dp dp方程
d p ( i , j ) dp(i,j) dp(i,j),代表从字符串 s i , s i + 1 . . . . . . s n s_i,s_i+1......s_n si,si+1......sn中选 j j j个字符串拼接到当前字符串上形成的最小字典序字符串,那么此时
d p ( i , j ) = m i n ( d p ( i + 1 , j ) , s i + d p ( i + 1 , j − 1 ) ) dp(i,j)=min(dp(i+1,j),s_i+dp(i+1,j-1)) dp(i,j)=min(dp(i+1,j),si+dp(i+1,j1))
因为如果我选了 s i s_i si,那么 d p ( i , j ) = s i + d p ( i + 1 , j − 1 ) dp(i,j)=s_i+dp(i+1,j-1) dp(i,j)=si+dp(i+1,j1)
如果我不选 s i s_i si以上是关于AtCoder Beginner Contest 225(补题)的主要内容,如果未能解决你的问题,请参考以下文章

AtCoder Beginner Contest 234

AtCoder Beginner Contest 115 题解

AtCoder Beginner Contest 154 题解

AtCoder Beginner Contest 103

AtCoder Beginner Contest 228

AtCoder Beginner Contest 242