数列找不同(莫队基础版)

86 篇文章 0 订阅

数列找不同

题目描述

现有数列 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

输出格式

对每个询问输出一行,YesNo

样例 #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,Q103
对于 100 % 100\% 100% 的数据, 1 ≤ N , Q ≤ 1 0 5 1 \le N,Q \le 10^5 1N,Q105 1 ≤ A i ≤ N 1 \le A_i \le N 1AiN 1 ≤ L i ≤ R i ≤ N 1 \le L_i \le R_i \le N 1LiRiN

代码

//基础莫队

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

const int N = 1e5+10;

int w[N];
struct E{
    int id,l,r;
}q[N];
int n,m;
int res,cnt[N];
int len;
int ans[N];

int get(int x){
    return x/len;
}

bool cmp(const E&a,const E&b){
    int i=get(a.l),j=get(b.l);
    if(i!=j)return i<j;
    return a.r<b.r;
}

void add(int x,int& res){
    if(!cnt[x])res++;
    cnt[x]++;
}

void del(int x,int& res){
    cnt[x]--;
    if(!cnt[x])res--;
}

int main(){
    cin>>n>>m;
    
    for(int i=1;i<=n;i++){
        cin>>w[i];        
    }
    
    for(int i=1;i<=m;i++){
        int l,r;
        cin>>l>>r;
        q[i]={i,l,r};
    }
    
    len=sqrt(n);
    sort(q+1,q+1+m,cmp);
    
    //i是右端点,j是左端点
    for(int k=1,i=0,j=1,res=0;k<=m;k++){
        int id=q[k].id,l=q[k].l,r=q[k].r;
        while(i<r)add(w[++i],res);
        while(i>r)del(w[i--],res);
        while(j<l)del(w[j++],res);
        while(j>l)add(w[--j],res);
        if(res==(r-l+1)){
            ans[id]=1;
        }
    }
    
    for(int i=1;i<=m;i++){
        // cout<<ans[i]<<endl;
        if(ans[i]==1){
            puts("Yes");
        }else{
            puts("No");
        }
    }
    
    return 0;
}
  • 18
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值