Codeforces-1672 D: Cyclic Rotation

Codeforces-1672 D: Cyclic Rotation

题目链接:Codeforces-1672 D

题目

题目截图

在这里插入图片描述

样例描述

在这里插入图片描述

题目大意

  给定一个数组长度 n n n,并给定数组 a a a
  可以对 a a a 数组实行一个操作,选择两个下标 l , r    for    1 ≤ l ≤ r ≤ n    a n d    a l = a r l, r \; \text{for}\; 1 \le l \le r \le n \; and \; a_l=a_r l,rfor1lrnandal=ar,将 a l a_l al 放到 a r a_r ar 的后面,此时 a [ l ⋯ r ] = [ a l + 1 , a l + 2 , ⋯   , a r , a l ] a[l\cdots r]=[a_{l+1},a_{l+2},\cdots,a_r,a_l] a[lr]=[al+1,al+2,,ar,al]
  现在给出另一个数组 b b b。问数组 a a a 能否通过变换,变为数组 b b b。(数据保证 b b b a a a 的重排列)

题目解析

  我们将这个过程反过来想,对 a a a 数组的操作的反过程 相当于 在 b b b 数组中选择两个连续且值相同的位置 i , i + 1 ; b [ i ] = b [ i + 1 ] i,i+1;b[i]=b[i+1] i,i+1;b[i]=b[i+1],且将 b [ i + 1 ] b[i+1] b[i+1] 替换到 i i i 之前的某个位置。
  那么,如果我们能够使用双指针法,在两个数组中分别反过来遍历:当 b [ i ] = b [ i + 1 ] b[i] = b[i+1] b[i]=b[i+1] 时,我们将 b [ i + 1 ] b[i+1] b[i+1] 储存起来,以便 b j b_j bj a i a_i ai 不相等时,取出储存的数放入,就能够从 b b b 数组恢复为 a a a 数组。值得注意的是当 b b b 中有很多个数连续相等的话,只取两个数 b [ i ] , b [ i + 1 ] b[i],b[i+1] b[i],b[i+1] 可能是不行的(对应下面代码中 while -> if 的情况),因为理论上整个连续相等的段,除了首元素,都可以被储存起来,如果只储存最后一位,之后就开始比较,就会浪费储存的机会,导致有时候找不到 a a a 中某个元素的对应值。例如 a = [ 2 , 2 , 1 , 2 ] , b = [ 1 , 2 , 2 , 2 ] a=[2, 2, 1, 2], b=[1,2,2,2] a=[2,2,1,2],b=[1,2,2,2],理论上可以从 a a a 变为 b b b,但若只存最后一个,判断就会变为不行。因此,要最大程度地利用储存插入这一性质。

Code

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 7;
int a[maxn], b[maxn], cnt[maxn];

int main() {
    int t, n;
    cin >> t;
    while(t--) {
        cin >> n;
        for(int i=1; i<=n; ++i) cin >> a[i];
        for(int i=1; i<=n; ++i) cin >> b[i];
        for(int i=1; i<=n; ++i) cnt[i] = 0;

        bool fl = true;
        for(int i=n, j=n; i>=1; --i) {
            while(j>1 && b[j] == b[j-1]) ++cnt[b[j]], --j;
            if(j>=1 && a[i] == b[j]) --j; else
            if(cnt[a[i]] > 0) --cnt[a[i]]; else {
                fl = false;
                cout << "NO" << endl;
                break;
            }
        }
        if(fl) cout << "YES" << endl;
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值