0
点赞
收藏
分享

微信扫一扫

Codeforces Round #529 (Div. 3) A~F题解


文章目录

  • ​​A. Repeating Cipher​​
  • ​​B. Array Stabilization​​
  • ​​C. Powers Of Two​​
  • ​​D. Circular Dance​​
  • ​​E. Almost Regular Bracket Sequence​​
  • ​​F. Make It Connected​​

A. Repeating Cipher

  • 解题思路
    按距离间距索引字符即可。
  • 参考代码
#include<bits/stdc++.h>

using namespace std;

int n;
string s;
int main(){
cin >> n >> s;
int idx = 0,cnt = 1;
while(idx < n){
cout << s[idx];
idx += cnt;
cnt ++;
}
cout << endl;
return 0;
}

B. Array Stabilization

  • 解题思路
    简单贪心,为了减小极差,要么删最大值要么删最小值。
  • 参考代码
#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;
int n,a[N];
void solve(){
sort(a + 1,a + 1 + n);
//要么删最大值要么删最小值。
printf("%d\n", min(a[n - 1] - a[1], a[n] - a[2]));
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
}
solve();
return 0;
}

C. Powers Of Two

  • 解题思路
    Codeforces Round #529 (Div. 3) A~F题解_#include按二进制位展开,那么展开后的每个二进制数都是Codeforces Round #529 (Div. 3) A~F题解_字符串_02的次幂。那么我们又知道对于Codeforces Round #529 (Div. 3) A~F题解_字符串_03,其可以转换成Codeforces Round #529 (Div. 3) A~F题解_字符串_02Codeforces Round #529 (Div. 3) A~F题解_算法_05,则会使个数加Codeforces Round #529 (Div. 3) A~F题解_算法_06 根据此原理,我们从高往低凑成Codeforces Round #529 (Div. 3) A~F题解_最小值_07Codeforces Round #529 (Div. 3) A~F题解_c++_08的次幂即可。
  • 参考代码
#include<bits/stdc++.h>

using namespace std;

int n,k;
int a[31];
void solve(){
a[0] = 1;
for(int i = 1; i < 31; ++ i){
a[i] = a[i - 1] * 2;
}
//我们将n拆成二进制,那么二进制上的每一位都是2的次幂,而每一个不是1的2的次幂又可以拆分成2个2的次幂。通过这种思想去凑k。
priority_queue<int> pos;
for(int i = 0; i < 31; ++ i){
if(n & a[i]){
pos.push(i);
}
}
//分解操作会使大小+1。如果可行那一定可以达到k。
while(pos.size() < k && pos.top() > 0){
int idx = pos.top();
pos.pop();
pos.push(idx - 1);
pos.push(idx - 1);
}
if(pos.size() == k){
cout << "YES" << endl;
while(!pos.empty()){
cout << a[(int)pos.top()] << " ";
pos.pop();
}
cout << endl;
}
else{
cout << "NO" << endl;
}
}
int main(){
cin >> n >> k;
solve();
return 0;
}

D. Circular Dance

  • 解题思路
    首先我们要知道,这实际上就是一个环,所以我们可以任取元素作为队头。而解决这道题目的关键就是确定一个元素的后两个元素的位置,那么可以根据后两个元素之间的关系来确定,因为第二个元素一定在第一个元素的后两个元素中。 这样循环迭代即可得出整个序列。
  • 参考代码
#include<bits/stdc++.h>
#define x first
#define y second

using namespace std;

const int N = 2e5 + 10;
int n;
pair<int,int> a[N];
void solve(){
//注意,这个相当于一个圈,所以我们可以任取队头。
//确定队头之后,怎么确定之后的两个元素的顺序呢。
vector<int> q;//队列q。
q.push_back(1);
int x = a[1].x, y = a[1].y;
bool flag = true;
//判断x的后两个元素是不是y。
if(a[x].x == y || a[x].y == y){
flag = false;
}
if(flag){
swap(x,y);//那么说明x的后一个元素不是y,则y在x前面,我们交换这两个值即可。保证x在前y在后。
}
q.push_back(x),q.push_back(y);
int len = q.size();
while(len < n){
int cur = a[x].x;
if(y == cur){
//说明cur是第一个元素,而我们要将第二个元素入队。
cur = a[x].y;
}
q.push_back(cur);
//这样一直迭代后两个元素。
len ++;
x = y;
y = cur;
}
for(int i = 0; i < len; ++ i){
cout << q[i] << " ";
}
cout << endl;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d%d", &a[i].x, &a[i].y);
}
solve();
return 0;
}

E. Almost Regular Bracket Sequence

  • 解题思路
    由于我们只能修改一个位置的括号,所以必然是只存在一对不合法的括号,我们将这个不合法的给找出来。再讨论情况。 那么我们可以利用栈来实现括号匹配,而当匹配完之后栈内必须要两个元素我们才可能实现。那么对于这其中的两个元素,我们需要判断是什么类型的,对于Codeforces Round #529 (Div. 3) A~F题解_c++_09Codeforces Round #529 (Div. 3) A~F题解_字符串_10我们都是可以是实现的,而Codeforces Round #529 (Div. 3) A~F题解_#include_11无论我们怎么修改都无法配对。
  • 参考代码
#include<bits/stdc++.h>

using namespace std;

int n;
string str;
void solve(){
//由于我们只能修改一个位置的括号,所以必然是只存在一对不合法的括号,我们将这个不合法的给找出来。再讨论情况。
stack<int> s;
for(int i = 0; i < n; ++ i){
if(str[i] == '('){
s.push(i);
}
else{
//碰到右括号就进行括号匹配。
if(!s.empty() && str[s.top()] == '('){
s.pop();
}
else{
s.push(i);//如果不能匹配就入队。
}
}
}
//最后栈的大小一定是2个。其他的则不合法。
int ans = 0;
if(s.size() == 2){
int idx2 = s.top();
s.pop();
int idx1 = s.top();
//分析判断。注意按idx1 < idx2,因为我们是按下标顺序入栈的。
if(str[idx1] == ')'){
if(str[idx2] == '('){
//)(当存在这种情况,我们无法修改使得其变为合法,因为进行操作只能对二者其中一个起作用。
ans = 0;
}
else{
//))当存在这种情况。我们将idx1左边的修改为(即可。
for(int i = 0; i <= idx1; ++ i){
if(str[i] == ')'){
ans ++;
}
}
}
}
else{
//说明是((类型,我们将)右边的修改为)即可。
for(int i = idx2; i < n; ++ i){
if(str[i] == '('){
ans ++;
}
}
}
}
cout << ans << endl;
}
int main(){
cin >> n >> str;
solve();
return 0;
}

F. Make It Connected

  • 解题思路
    最小生成树模板题。特别需要注意的一点就是我们不需要存储Codeforces Round #529 (Div. 3) A~F题解_字符串_12条边,根据贪心原则我们会选取权值较小的边构建Codeforces Round #529 (Div. 3) A~F题解_最小值_13,所以我们可以对顶点权排序,通过点权最小的点和其他点构建Codeforces Round #529 (Div. 3) A~F题解_算法_14条边即可,剩下的即可舍去。既而我们再考虑增添的Codeforces Round #529 (Div. 3) A~F题解_算法_15条边,将这些边组合排序进行Kruskal算法实现即可。
  • 参考代码
#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

typedef long long ll;

int n,m;
struct node{
int u;
ll w;
bool operator < (const node &A){
return w < A.w;
}
}nodes[N];
struct edge{
int u,v;
ll w;
bool operator < (const edge &A){
return w < A.w;
}
}edges[N << 2];
int tot,father[N];
int find(int x){
int r = x;
while(r != father[r])r = father[r];
int i = x,j;
while(father[i] != r){
j = father[i];
father[i] = r;
i = j;
}
return r;
}
void solve(){
sort(nodes + 1, nodes + 1 + n);
for(int i = 2; i <= n; ++ i){
//如果不适用魔法,而是直接连接的话必然是选择权值较小的,则以最小的与其他n-1个点相连即可。
edges[++ tot].u = nodes[1].u;
edges[tot].v = nodes[i].u;
edges[tot].w = nodes[i].w + nodes[1].w;
}
sort(edges + 1, edges + 1 + tot);
for(int i = 1; i <= n; ++ i)father[i] = i;
ll ans = 0;
for(int i = 1; i <= tot; ++ i){
int fu = find(edges[i].u), fv = find(edges[i].v);
if(n == 1)break;//当集合只剩一下即连通。
if(fu != fv){
father[fu] = fv;
ans += edges[i].w;
n --;
}
}
printf("%lld\n", ans);
}
int main(){
scanf("%d%d", &n ,&m);
for(int i = 1; i <= n; ++ i){
scanf("%lld", &nodes[i].w);
nodes[i].u = i;
}
for(int i = 1; i <= m; ++ i){
tot ++;
scanf("%d%d%lld", &edges[tot].u, &edges[tot].v, &edges[tot].w);
}
solve();
return 0;
}


举报

相关推荐

0 条评论