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;
}