Codeforces Round #793 (Div. 2)

目录

A. Palindromic Indices

B. AND Sorting

C. LIS or Reverse LIS?


A. Palindromic Indices

A. Palindromic Indices

题目翻译: 给定一个回文串,问:可以最多拿走多少字符,使字符串仍然为回文串

思路:取一个字符串 t 为中间值,向左枚举,当枚举的字符串不等于中间字符串时,结束循环

n 奇数时:取 t = n/2,t 为正中间的字符串,去掉的字符串应该与中间的字符串相等时,可以去除该字符串,因为左右相等,所以去除左右是一样的因此 res += 2,使的去掉后的字符串仍然为回文字符串

n 偶数时:取t = n/2 ,t 为正中间一对字符串中的一个,向左枚举与上述操作类似

代码如下

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;
typedef long long LL;

const int N = 2e5+10;

int T;

void solve()
{
    int cnt = 0;
    int n;
    cin >> n;
    string s;
    cin >> s;

    if(s.size()%2)
    {
        char t = s[s.size()/2];
        cnt = 1;
        for(int i = s.size()/2-1; i >= 0; i -- )
            if(s[i] == t) cnt += 2;
            else break;
    }
    else
    {
        char t = s[s.size()/2];
        for(int i = s.size()/2-1; i >= 0; i -- )
            if(s[i] == t) cnt += 2;
            else break;
    }

    cout << cnt << endl;

    return;
}

int main()
{
    scanf("%d", &T);

    while(T -- )
        solve();

    return 0;
}

B. AND Sorting

B. AND Sorting 

题目翻译:给定数组数组p,其中元素为 0~n-1,随机顺序但数组元素不重复,存在一个 x ,使得当 p[i] & p[j] == x 时,可以交换 p[i] 和 p[j] ,请问:求出最大的 x 使得交换过的数组为升序

思路: 

(1)判断最大的 x :当两个元素交换时,有两种方式交换,直接交换 ( swap(p[i], p[j]) ) ,通过第三者交换 (swap(p[i], p[t]) , swap(p[t], p[j] ) ,第一种直接交换 x = p[i] & p[j] ,第二种 x = p[i] & p[t] & p[j] ,很明显第二种的 x <= 第一种的 x ,& p[t] 有风险,所以我们可以确定大致思路为,将要交换的值 & 起来

(2)如果要交换 p[i] & p[j] == x , p[k] & p[l] == x,可知 x 的 1 的位置与上述的四个数的 1 的位置重叠,即,可以表示为 p[i] & p[j] & p[k] & p[l] = x,如此将所有要交换的值 & 起来即可

因为元素为 0~n-1恰好为索引值,所以我们排列好的数组的值,因该与索引值一致,所以,原数组中与索引值不一致的数为要交换的数,结果为,将所有值与索引不一致的数 & 与 起来即可

初始化:将 x 可能用到的位置为 1 ,1 << 20 二进制表示为 1 后面19个0,(1 << 20) - 1 为 19位1,大于 2e5

代码如下: 

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;
typedef long long LL;

const int N = 2e5+10;

int T;

void solve()
{
    int n;
    scanf("%d", &n);
    vector<int> a(n+10), b;
    for(int i = 0; i < n; i ++ )
        scanf("%d", &a[i]);

    int x = (1 << 20) - 1;
    for(int i = 0; i < n; i ++ )
        if(a[i] != i) x &= a[i];

    cout << x << endl;

    return;
}

int main()
{
    scanf("%d", &T);

    while(T -- )
       solve();

    return 0;
}

C. LIS or Reverse LIS?

C. LIS or Reverse LIS?

题目翻译:给数组a,任意排序,使得最大上升子序列的值 LIS(a) (LIS1),反转后的最大上升子序列LIS(a') (LIS2) ,二者取 min 的数最大

思路

解读题意:查找最大上升子序列与最大下降子序列取 min 的最大值,即两序列所含数目应尽可能的接近

(1)两序列最多只能包含一个公共的索引(即,最大值的索引)

(2)给定一个数值,他只能有三个位置可以去,LIS1,LIS2,LIS1&LIS2(只在LIS1中出现,只在LIS2中出现,即在LIS1中出现又在LIS2中出现),

(3)若为本数值的数的个数大于等于2,说明可以令其中一个取LIS1,令另一个取LIS2,即LIS1与LIS2中都存在此数,若此数的个数为1,说明他只能取一个序列中

所以答案为 两个都能去的数值 + 【(唯一的数个数为奇数)唯一的数的个数/2 (下取整)  + 1 或(唯一的数个数为偶数)唯一的数的个数/2】

第二项合并为:(唯一的数的个数+1)/2(下取整)

代码如下

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;
typedef long long LL;

const int N = 2e5+10;

int T;

void solve()
{
    int n;
    scanf("%d", &n);
    vector<int> a(n+10), b;
    for(int i = 0; i < n; i ++ )
        scanf("%d", &a[i]);

    int x = (1 << 20) - 1;
    for(int i = 0; i < n; i ++ )
        if(a[i] != i) x &= a[i];

    cout << x << endl;

    return;
}

int main()
{
    scanf("%d", &T);

    while(T -- )
       solve();

    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AC自动寄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值