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) (xi−1,yi)构成的线段和 ( x i , y i ) (x_i,y_i) (xi,yi)与 ( x i , y i − 1 ) (x_i,y_i-1) (xi,yi−1)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)
(xi−1,yi)和
(
x
i
,
y
i
−
1
)
(x_i,y_i-1)
(xi,yi−1)构成的图形,就是以
(
x
i
−
1
,
y
i
)
(x_i-1,y_i)
(xi−1,yi)
(
x
i
,
y
i
−
1
)
(x_i,y_i-1)
(xi,yi−1)和原点所形成的两条直线所占据的图形,这两条直线的斜率为
k
1
和
k
2
k1和k2
k1和k2。如果某条直线与当前这个图形的两条直线有交点,那就说明这条直线的斜率在
[
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,j−1))
因为如果我选了
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,j−1)
如果我不选
s
i
s_i
si以上是关于AtCoder Beginner Contest 225(补题)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解