数列找不同
题目描述
现有数列 A 1 , A 2 , … , A N A_1,A_2,\ldots,A_N A1,A2,…,AN, Q Q Q 个询问 ( L i , R i ) (L_i,R_i) (Li,Ri),询问 A L i , A L i + 1 , … , A R i A_{L_i} ,A_{L_i+1},\ldots,A_{R_i} ALi,ALi+1,…,ARi 是否互不相同。
输入格式
第一行,两个整数
N
,
Q
N,Q
N,Q。
第二行,
N
N
N 个整数
A
1
,
A
2
,
…
,
A
N
A_1, A_2, \ldots , A_N
A1,A2,…,AN。
接下来
Q
Q
Q 行,每行两个整数
L
i
,
R
i
L_i,R_i
Li,Ri。
输出格式
对每个询问输出一行,Yes
或 No
。
样例 #1
样例输入 #1
4 2
1 2 3 2
1 3
2 4
样例输出 #1
Yes
No
提示
对于
50
%
50\%
50% 的数据,
N
,
Q
≤
1
0
3
N,Q \le 10^3
N,Q≤103。
对于
100
%
100\%
100% 的数据,
1
≤
N
,
Q
≤
1
0
5
1 \le N,Q \le 10^5
1≤N,Q≤105,
1
≤
A
i
≤
N
1 \le A_i \le N
1≤Ai≤N,
1
≤
L
i
≤
R
i
≤
N
1 \le L_i \le R_i \le N
1≤Li≤Ri≤N。
原题链接
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 6;
int cnt[maxn]; //记录某个数出现的次数
int sum, a[maxn], n, q, bl, ans[maxn], curL = 1, curR = 0;
// sum就是所求答案,bl是分块数量,a[]是原序列,ans[]是记录原查询序列下的答案,n表示数组大小,q表示询问个数。
void add(int pos) // 添加
{
cnt[a[pos]]++;
if (cnt[a[pos]] == 1)
sum++; //sum统计的是不同的数的个数,当操作后cnt==1,sum++
}
void del(int pos) // 去除
{
cnt[a[pos]]--;
if (cnt[a[pos]] == 0)
sum--; //sum统计的是不同的数的个数,当操作后cnt==0,sum--
}
struct query //询问 结构体
{
int l, r, p;
} e[maxn];
bool cmp(query a, query b)
{
// 记得在主函数中对bl赋值(bl=sqrt(n))
return (a.l / bl) == (b.l / bl) ? a.r < b.r : a.l < b.l;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> q;
bl = sqrt(n); //分块数量的赋值
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= q; i++)
{
cin >> e[i].l >> e[i].r;
e[i].p = i; //记录询问的顺序
}
sort(e + 1, e + 1 + q, cmp); //对询问进行桶排序
for (int i = 1; i <= q; i++)
{
int l = e[i].l;
int r = e[i].r;
int p = e[i].p;
// 莫队
while (curL < l)
{
del(curL);
curL++;
}
while (curL > l)
{
curL--;
add(curL);
}
while (curR < r)
{
curR++;
add(curR);
}
while (curR > r)
{
del(curR);
curR--;
}
if (sum == r - l + 1) //不同的数个数等于区间长度 则说明区间元素互不相同
{
ans[p] = 1; //ans[]为1表示该询问中区间元素互不相同
}
}
for (int i = 1; i <= q; i++)
{
if (ans[i] == 1)
{
cout << "Yes" << '\n';
}
else
{
cout << "No" << '\n';
}
}
return 0;
}