cf2117E

原题链接:https://codeforces.com/contest/2117/problem/E
题目背景:

       给定两个数组a,b,可以执行多次以下操作:选择 i (1 <= i <= n - 1),并设置 a_i = b_{i+1}b_i = a_{i+1},也可以在执行上述操作前执行一次删除任意 a_i 和 b_i。求最大匹配数,a_i = b_i 即可算得一点匹配数。

思路:

       通过题目不难发现以下几点规律:

  1. 如果 a_{n-1} == b_{n-1},其答案就为 n 。
  2. 如果 a_i == b_i ,就可以将 i 之前所有的元素都变成相同的元素,既答案为 i 。
  3. 如果 a_i == a_{i+1} 或 b_i == b_{i+1},也可以将 i 之前所有的元素都变成相同的元素。
  4. 如果当前 a_i 或 b _i,在 i + 1 (不包含) 之后出现过,也可以将 i 之前所有的元素都变成相同的元素。

        第四条证明:设 a = [1,2,5,4,6],b = [3,3,2,1,3],st[num]表示num在i+1之后是否出现过。

        逆推从 i = 4 开始(下标从0开始);

        首先 i = 4, 6 != 3。

        i = 3,4 != 1 && 4 != 3 && 1 != 6;将 st[6] = st[3] = 1。

        i = 2,5 != 2 && 5 != 4 && 2 != 1 && st[5] == 0 && st[2] ==0;将 st[4] = st[1] = 1

        i = 1,st[2] = 1,答案为2。

        图解(数字右下角的红色数字代表可以通过操作将数字变为红色数字):

        

        如果样例是 a = [1,2,5,4,3],b = [3,3,2,1,6] 呢?

        我们还有一个操作2可以在执行全部所以操作之间使用,只需删除中间的任意一对元素即可。

        图解:

数据范围:

        n 总和不超过 2e5。

时间复杂度:

        O(n)。

ac代码: 
#include <bits/stdc++.h>

#define ioscc ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define me(a, x) memset(a, x, sizeof a)
#define all(a) a.begin(), a.end()
#define sz(a) ((int)(a).size())
#define pb(a) push_back(a)
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;

const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, 1, 0, -1};
const int MAX = (1ll << 31) - 1;
const int MIN = 1 << 31;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) noexcept
{
    for (int i = 0; i < sz(a) - 10; i++)
        std::cout << a[i] << ' ';
    return os;
}

template <class T>
istream &operator>>(istream &in, vector<T> &a) noexcept
{
    for (int i = 0; i < sz(a) - 10; i++)
        std::cin >> a[i];
    return in;
}

/* ----------------- 有乘就强转,前缀和开ll ----------------- */

void solve()
{
    int n;
    cin >> n;
    vi a(n + 10), b(n + 10);
    cin >> a >> b;

    if (a[n - 1] == b[n - 1])
    {
        cout << n << endl;
        return;
    }

    vi st(n + 10, 0);
    ll ans = 0;
    for (int i = n - 2; ~i; --i)
    {
        if (a[i] == a[i + 1] || b[i + 1] == b[i] || a[i] == b[i] || st[a[i]] || st[b[i]])
        {
            ans = i + 1; // 下标从0开始
            break;
        }

        st[a[i + 1]] = st[b[i + 1]] = 1;
    }

    cout << ans << endl;
}

int main()
{
    ioscc;

    int T;
    cin >> T;
    while (T--)
        solve();

    return 0;
}

07-24
CF1583E 是 Codeforces 平台上的一道编程竞赛题目,题目标题为 "Cesium",属于 Codeforces Round #760 (Div. 3) 的一部分。这道题目的核心是构造一个满足特定条件的排列(permutation),并且要求选手能够处理不同情况下的构造逻辑。 题目大意是给定一个长度为 $ n $ 的排列 $ p $,要求构造一个排列,使得对于每个位置 $ i $,其值 $ p_i $ 满足以下条件之一: - $ p_i = i $ - $ p_i = i + 1 $ - $ p_i = i - 1 $ 换句话说,每个元素必须与其索引值相邻(包括等于自身索引的情况)。如果无法构造这样的排列,则输出 `-1`。 解题的关键在于理解哪些 $ n $ 值可以构造出满足条件的排列,并找出构造策略。通过分析,可以发现: - 当 $ n \equiv 2 \mod 3 $ 时,无法构造出满足条件的排列。 - 构造方法通常采用分块策略,例如将排列按照 2、1、3 的模式循环构造,例如 $ [2, 1, 3] $,$ [2, 1, 3, 4] $,等等,以确保每个元素都满足条件[^1]。 以下是一个 Python 实现的示例代码,用于判断是否可以构造满足条件的排列,并输出结果: ```python def solve(n): if n % 3 == 2: print(-1) return res = [] for i in range(1, n + 1, 3): if i + 1 <= n: res.append(i + 1) res.append(i) else: res.append(i) if i + 2 <= n: res.append(i + 2) print(' '.join(map(str, res))) # 示例输入 solve(5) # 输出示例:2 1 3 5 4 ``` 在上述代码中,构造逻辑基于每三个连续的数字,将中间的两个数字交换位置,同时保留第三个数字。这样可以确保所有元素都满足题目要求。 ### 相关问题 1. 如何判断一个排列是否满足 CF1583E 的构造条件? 2. 为什么当 $ n \equiv 2 \mod 3 $ 时无法构造满足条件的排列? 3. CF1583E 的构造策略是否唯一?是否存在其他构造方法? 4. 如何调整 CF1583E 的构造逻辑以适应不同的排列长度? 5. 在编程竞赛中,如何快速识别类似 CF1583E 的构造问题并设计解决方案?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值