Loading

AtCoder-abc250_e Prefix Equality

Prefix Equality

给出两个数组 \(a\) \(b\),问 \(a\) 数组前 \(x_i\) 个 和 \(b\) 数组前 \(y_i\) 个,这两组各自形成的集合是否相等

尺取

我用的是尺取过的,但是看了别人的题解,好像都是用哈希来预处理 \(a\) 的前缀集合 还有 \(b\) 的前缀集合,然后直接判断是否相等

我认为,如果选定了 \(a\) 数组的前 \(i\) 个,则在 \(b\) 数组中,一定有一个范围 \([l, r]\) 使得答案成立

并且对于这个范围,有 \(l_{i} \leq l_{i+1}\)\(r_{i} \leq r_{i+1}\),因此可以判断他是单调的,所以直接尺取区间就行,尺取复杂度为 \(O(n)\)

因为要维护一个桶,所以用了 \(map\)

总的时间复杂度为 \(O(nlogn)\)

#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const int maxn = 2e5 + 10;
int a[maxn], b[maxn];
pii num[maxn];

int main()
{
    int n;
    scanf("%d", &n);
    map<int, int> r_vis, l_vis;
    for(int i=1; i<=n; i++) scanf("%d", &a[i]);
    for(int i=1; i<=n; i++) scanf("%d", &b[i]);
    b[++n] = a[1];
    int l = 1, r = 1, cnt = 0;
    for(int i=1; i<=n; i++)
    {
        if(r_vis[a[i]] == 0) r_vis[a[i]] = 1;
        if(l_vis[a[i]] == 0) {cnt++; l_vis[a[i]] = 1;}
        while(l <= n && cnt > 0)
        {
            if(l_vis[b[l]] == 1) cnt--;
            l_vis[b[l]] = 2;
            l++;
        }
        while(r <= n && r_vis[b[r]]) r++;
        num[i] = make_pair(l - 1, r - 1);
    }
    int m;
    scanf("%d", &m);
    for(int i=0; i<m; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        if(y >= num[x].first && y <= num[x].second) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
posted @ 2022-05-13 20:00  dgsvygd  阅读(75)  评论(0编辑  收藏  举报