P3901 数列找不同(莫队)
传送门:数列找不同
显然一个区间的答案可以 \(O(1)\) 转移到相邻区间,记录每个数的 \(cnt\)。当 \(cnt = 2\) 时,表示多出现了一个相同的,记录增加。同理,当 \(cnt = 1\) 的时候,表示少了一个相同的,记录减少。跑一遍莫队即可,时间复杂度 \(O(n\sqrt n)\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100000 + 10;
struct unit
{
int l,r,id;
} q[N];
int n,m,l = 1,r,block,res;
int a[N],cnt[N],L[N],R[N],spl[N];
map < int ,string > ans;
bool cmp(unit aa,unit bb)
{
if(spl[aa.l] != spl[bb.l]) return spl[aa.l] < spl[bb.l];
if(spl[aa.l] & 1) return aa.r < bb.r;
else return aa.r > bb.r;
}
void modify(int x,int val)
{
cnt[a[x]] += val;
if(val == 1) res += (cnt[a[x]] == 2);
else res -= (cnt[a[x]] == 1);
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i = 1;i <= n;i++) scanf("%lld",&a[i]);
block = sqrt(n);
for(int i = 1;i <= block;i++)
{
L[i] = (i - 1) * block + 1;
R[i] = i * block;
}
if(R[block] < n) block++,L[block] = R[block - 1] + 1,R[block] = n;
for(int i = 1;i <= block;i++)
for(int j = L[i];j <= R[i];j++)
spl[j] = i;
for(int i = 1;i <= m;i++)
{
scanf("%lld%lld",&q[i].l,&q[i].r);
q[i].id = i;
}
sort(q + 1,q + m + 1,cmp);
for(int i = 1;i <= m;i++)
{
while(l > q[i].l) modify(--l,1);
while(r < q[i].r) modify(++r,1);
while(l < q[i].l) modify(l++,-1);
while(r > q[i].r) modify(r--,-1);
ans[q[i].id] = res ? "No" : "Yes";
}
for(int i = 1;i <= m;i++) cout << ans[i] << endl;
return 0;
}

浙公网安备 33010602011771号