Codeforces Round #793 (Div. 2)(A-D)

目录

A. Palindromic Indices

B. AND Sorting

C. LIS or Reverse LIS?

D. Circular Spanning Tree


A. Palindromic Indices

Problem - A - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1682/problem/A

题意:给你一个回文串,你可以删除一个字符串,保证这个回文串还是一个回文串,问有几种删法

思路:只需要把中间一段相同的字符删除一个即可.

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
    int n;
    string s;
    cin>>n>>s;
    int cnt=0;
    if(s.size()%2==0)
    {
        int l=(s.size()-1)/2;
        for(int i=l;i>=0;i--)
        {
            if(s[i]==s[l])
                cnt++;
            else 
                break;
        }
        cnt*=2;
    }
    else
    {
        int l=s.size()/2;
        for(int i=l;i>=0;i--)
        {
            if(s[i]==s[l])
                cnt++;
            else 
                break;
        }
        cnt=cnt*2-1;
    }
    cout<<cnt<<"\n";
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

B. AND Sorting

Problem - B - Codeforcesicon-default.png?t=M5H6https://codeforces.com/contest/1682/problem/B

题意:给你一个数组,有原本的升序的数组得来(原本是0,1,2,3...n-1),存在一个x,当(a[i]&a[j])==x的时候,即可进行交换,问当x最大是多少的时候我们可以从原数组得到题目所给的数组.

思路:要让x作为中转站可以将所有的不同位置上的数字进行两两交换,吧不在原来位置上的数字相&即可:

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
    int n,x;
    cin>>n;
    int ans=-1;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        if(ans==-1&&x!=i-1)
        {
            ans=x;
        }
        else if(ans!=-1&&x!=i-1)
        {
            ans&=x;
        }
    }
    cout<<ans<<"\n";
    return ;
}
signed main()
{ 
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

C. LIS or Reverse LIS?

Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1682/problem/C

题意:给你一个数组,你可以在它重新排列之后,求得它的正向的严格最长上升子序列的长度还有反向的严格最长上升子序列的长度.两者取最小值,求这个最小值最大是多少.

思路:我们用map记录所有数组元素的个数,map的长度即为他升序的最长长度,然后我们统计这个升序序列中每个元素超过2个的个数,将他们拼在右边,即为反向最长上升子序列的长度,但是由于可能左边的正向最长上升子序列的长度大于右边的反向最长上升子序列的长度.我们可以适当地把左边的一些数字移动到右边去.举个例子:

数组

1 1 1 2 3 4 4 4 4 4 4 5 6 6

我们进行操作后,分别把反向和正向的最长上升子序列放在两边:

1 2 3 4 5 6    6 4 1

这个时候结果的值为3,但是我们发现可以适当地移动一些左边的值到右边,就变成了:

1 2 4 5 6      6 4 3 1

如上操作即可求出答案

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
using namespace std;
const int N =5e5+10,mod=998244353;
map<int,int>ma;
int a[200005];
void solve()
{ 
    ma.clear();
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>x,ma[x]++;
    if(n==1)
    {
        cout<<"1\n";
        return ;
    }
    int len1=ma.size(),len2=0;
    for(auto &it:ma)
    {
        if(it.second>=2)
            len2++;
    }
    int ans=(len1+len2+1)/2;
    cout<<ans<<"\n";
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

D. Circular Spanning Tree

Problem - D - Codeforcesicon-default.png?t=M5H6https://codeforces.com/contest/1682/problem/D

题意:给你一个字符串,(0-n-1)对应1-n点的度数的奇偶性,当当前的点的度数为奇数的时候,字符表示为'1',反之为'0'.我们要根据这个字符串构造一棵树出来.

思路:首先排除不可能成立的情况.我们知道树存在n-1调边,那么肯定存在偶数个度数为奇数的点,而且这些点度数要大于0.那么除此之外直接输出NO.

然后就是对于树的构造.我们可以把每个度数为奇数的点作为一条链的头,因为度数为奇数的点肯定有偶数个,那么必定有偶数条链,我们直接把链尾相连(都连到同一条链子的链尾,这样可以避免交叉).这样每个链尾本身有度数1,再去链接奇数个点,度数肯定就变成了偶数.即可成立.

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
using namespace std;
vector<int>wei;
void solve()
{
    wei.clear();
    int n,st=0;
    string s;
    cin>>n>>s;
    int cnt=0,len=s.size();
    for(int i=0;i<len;i++)
    {
        if(s[i]=='1')
            cnt++,st=i;
    }
    if(cnt<2||cnt%2==1)
    {
        cout<<"NO\n";
        return ;
    }
    cout<<"YES\n";
    for(int i=0;i<len;i++)
    {
        if(s[(st+i+1)%len]=='1')   
        {
            wei.push_back((st+i)%len);
            continue;
        }
        cout<<(st+i)%len+1<<" "<<(st+i+1)%len+1<<"\n";
    }
    for(int i=1;i<wei.size();i++)
    {
        cout<<wei[0]+1<<" "<<wei[i]+1<<"\n";
    }
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值