题目大意
给定一个长度为
n
的序列
每个询问
Data Constraint
n,m≤100000,ai≤10000
题解
先考虑求区间
[1,r]
的答案。
ai=kp+q
当
p
很大时,
所以维护
h[i]
表示
i
有多少个,
当
p
很大时在
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define K 100000 + 10
#define N 10000 + 10
#define M 100 + 10
struct Query {
int h ;
int l , r , p , q ;
} Q[K] ;
int h[N] , g[M][M] ;
int a[K] , ans[K] ;
int n , m ;
bool cmpr( Query a , Query b ) { return a.r < b.r || ( a.r == b.r && a.l < b.l ) ; }
bool cmpl( Query a , Query b ) { return a.l < b.l || ( a.l == b.l && a.r < b.r ) ; }
int main() {
scanf( "%d%d" , &n , &m ) ;
for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &a[i] ) ;
for (int i = 1 ; i <= m ; i ++ ) scanf( "%d%d%d%d" , &Q[i].l , &Q[i].r , &Q[i].p , &Q[i].q ) , Q[i].h = i ;
sort( Q + 1 , Q + m + 1 , cmpr ) ;
int top = 1 ;
for (int i = 1 ; i <= n && top <= m ; i ++ ) {
h[a[i]] ++ ;
for (int k = 1 ; k <= 100 ; k ++ ) g[k][a[i]%k] ++ ;
while ( top <= m && Q[top].r == i ) {
if ( Q[top].p <= 100 ) ans[Q[top].h] += g[Q[top].p][Q[top].q] ;
else {
for (int k = 0 ; Q[top].p * k + Q[top].q <= 10000 ; k ++ ) ans[Q[top].h] += h[Q[top].p * k + Q[top].q] ;
}
top ++ ;
}
}
top = 1 ;
memset( h , 0 , sizeof(h) ) ;
memset( g , 0 , sizeof(g) ) ;
sort( Q + 1 , Q + m + 1 , cmpl ) ;
for (int i = 1 ; i <= n && top <= m ; i ++ ) {
while ( top <= m && Q[top].l == i ) {
if ( Q[top].p <= 100 ) ans[Q[top].h] -= g[Q[top].p][Q[top].q] ;
else {
for (int k = 0 ; Q[top].p * k + Q[top].q <= 10000 ; k ++ ) ans[Q[top].h] -= h[Q[top].p * k + Q[top].q] ;
}
top ++ ;
}
h[a[i]] ++ ;
for (int k = 1 ; k <= 100 ; k ++ ) g[k][a[i]%k] ++ ;
}
for (int i = 1 ; i <= m ; i ++ ) printf( "%d\n" , ans[i] ) ;
return 0 ;
}
以上.