[Hackerrank Week of Code 30]Range Modular Queries

題目大意

給出一個序列a[1..n]
q個詢問形如”l r x y”問a[l..r]中a[i]modx=y 的個數
1n,a[i]40000

題解

對於x200 ,將a[]分成n 塊,預處理s[i][x][y] 表示前i塊中模x等於y的數的個數,然後詢問時可以直接用s和暴力查詢多出的部分,一次詢問的時間複雜度爲O(n)
對於x200 ,那麼滿足tmodx=y 的不同的t的個數最多隻有40000x ,那麼這一部分可以使用Mo’s algorithm,用桶來維護每種值出現的次數,然後詢問時就直接詢問,一次詢問的複雜度是O(n)
總的時間複雜度是O((n+q)n)

Code

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>

#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)

using namespace std;

typedef long long LL;
typedef double db;

const int N = 40010;
const int blk = 200;

int get(){
    char ch;
    while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');
    if (ch=='-'){
        int s=0;
        while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
        return -s;
    }
    int s=ch-'0';
    while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
    return s;
}

int s1[blk+10][blk+10][blk+10];
int s2[N];
int n,q,a[N],q1,mv;
int bl[N];
struct query{
    int id,l,r,x,y;

    friend bool operator < (query a,query b){
        if (bl[a.l]!=bl[b.l])return bl[a.l]<bl[b.l];
        return a.r<b.r;
    }
}t[N];
int ans[N];

int getv(int w,int x,int y){
    if (w==0)return 0;
    int v=s1[x][bl[w]-1][y];
    fo(i,(bl[w]-1)*blk+1,w)if (a[i]%x==y)v++;
    return v;
}

void solve(){
    sort(t+1,t+1+q1);
    int l=1,r=0;
    fo(i,1,q1){
        while(l<t[i].l)s2[a[l++]]--;
        while(l>t[i].l)s2[a[--l]]++;
        while(r>t[i].r)s2[a[r--]]--;
        while(r<t[i].r)s2[a[++r]]++;
        fo(j,0,mv/t[i].x)
        if (j*t[i].x+t[i].y<=40000)
            ans[t[i].id]=ans[t[i].id]+s2[j*t[i].x+t[i].y];
    }
}

int main(){
    n=get();q=get();
    fo(i,1,n){a[i]=get();mv=max(mv,a[i]);}
    fo(i,1,n)bl[i]=(i-1)/blk+1;
    int tp=bl[n];
    fo(x,1,blk){
        fo(i,1,n)s1[x][bl[i]][a[i]%x]++;
        fo(i,1,tp)fo(j,0,x-1)s1[x][i][j]+=s1[x][i-1][j];
    }
    fo(i,1,q){
        int l=get()+1,r=get()+1,x=get(),y=get();
        if (x<=blk)ans[i]=getv(r,x,y)-getv(l-1,x,y);
        else{
            t[++q1].l=l;t[q1].r=r;
            t[q1].x=x;t[q1].y=y;
            t[q1].id=i;
        }
    }
    solve();
    fo(i,1,q)printf("%d\n",ans[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章