题目描述
为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为k。因为一些特殊的原因,不会出现一个查询的用户区间完全覆盖另一个查询的用户区间(不存在L1<=L2<=R2<=R1)。
输入描述:
输入: 第1行为n代表用户的个数 第2行为n个整数,第i个代表用户标号为i的用户对某类文章的喜好度 第3行为一个正整数q代表查询的组数 第4行到第(3+q)行,每行包含3个整数l,r,k代表一组查询,即标号为l<=i<=r的用户中对这类文章喜好值为k的用户的个数。 数据范围n <= 300000,q<=300000 k是整型
输出描述:
输出:一共q行,每行一个整数代表喜好值为k的用户的个数
示例1
输入
5 1 2 3 3 5 3 1 2 1 2 4 5 3 5 3
输出
1 0 2
说明
样例解释: 有5个用户,喜好值为分别为1、2、3、3、5, 第一组询问对于标号[1,2]的用户喜好值为1的用户的个数是1 第二组询问对于标号[2,4]的用户喜好值为5的用户的个数是0 第三组询问对于标号[3,5]的用户喜好值为3的用户的个数是2
思路:我的做法是采用离线处理查询,首先将所有查询按照区间左端点进行排序,并定义两个指针来进行尺取,对于每个当前查询,我们能够快速求出这个区间中存在的不同喜好值的数量,最后保存答案即可。
import java.util.*;
public class Main{
public static void main(String[] args){
int n,q;
Scanner in=new Scanner(System.in);
n=in.nextInt();
int[] a=new int[n+1];
for(int i=1;i<=n;i++)
a[i]=in.nextInt();
q=in.nextInt();
int[] ans=new int[q];
int[][] arr=new int[q][4];
for(int i=0;i<q;i++){
arr[i][0]=in.nextInt();
arr[i][1]=in.nextInt();
arr[i][2]=in.nextInt();
arr[i][3]=i;
}
Arrays.sort(arr,(aa,bb)->aa[0]==bb[0]?aa[1]-bb[1]:aa[0]-bb[0]);
Map<Integer,Integer> count=new HashMap<>();
int l=arr[0][0],r=arr[0][1];
for(int i=l;i<=r;i++){
if(!count.containsKey(a[i]))
count.put(a[i],1);
else
count.put(a[i],count.get(a[i])+1);
}
ans[arr[0][3]]=count.getOrDefault(arr[0][2],0);
for(int i=1;i<q;i++){
while(r<arr[i][1]){
r++;
if(!count.containsKey(a[r]))
count.put(a[r],1);
else
count.put(a[r],count.get(a[r])+1);
}
while(l<arr[i][0]){
count.put(a[l],count.get(a[l])-1);
l++;
}
ans[arr[i][3]]=count.getOrDefault(arr[i][2],0);
}
for(int i=0;i<q;i++)
System.out.println(ans[i]);
}
}