为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为k。因为一些特殊的原因,不会出现一个查询的用户区间完全覆盖另一个查询的用户区间(不存在L1<=L2<=R2<=R1)。
为了不断优化推荐效果,今日头条每天要存储和处理海量数据。假设有这样一种场景:我们对用户按照它们的注册时间先后来标号,对于一类文章,每个用户都有不同的喜好值,我们会想知道某一段时间内注册的用户(标号相连的一批用户)中,有多少用户对这类文章喜好值为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的用户的个数
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
n = int(input()) #这道题用暴搜肯定超时,但是用Python的字典会非常简单
user_array = list(map(int,input().strip().split()))
user_dict = dict() #创建一个字典
for i in range(len(user_array)): #对应的键值是用户喜爱程度,value值是一个列表,对应相应的用户id
if user_dict.__contains__(user_array[i]):
user_array_list_i = list(user_dict[user_array[i]])
user_array_list_i.append(i+1)
user_dict[user_array[i]] = user_array_list_i
else:
user_array_list_i = []
user_array_list_i.append(i+1)
user_dict[user_array[i]] = user_array_list_i
q = int(input())
for i in range(q):
query = list(map(int,input().strip().split()))
start_index = query[0]
end_index = query[1]
k = query[2]
if user_dict.__contains__(k):
query_list = user_dict[k] #通过键值找到这个喜爱程度对应所有的用户id
count = 0
for j in range(len(query_list)):
if start_index <= query_list[j] <= end_index:
count += 1
print(count)
else:
print(0)
<?php// 已通过所有用例functiongetArrFromLine($pattern,$split,$num) {$arr= [];$p_str= "";for($i= 0; $i<$num; $i++) {if($i!= $num-1){$p_str.= "{$pattern}{$split}";}else{$p_str.= "{$pattern}\n";}//$arr[$i] = null;}$paramters= [STDIN,$p_str];for($i= 0; $i<$num; $i++) {$paramters[$i+2] = &$arr[$i];}call_user_func_array('fscanf',$paramters);return$arr;}fscanf(STDIN, "%d",$users);$karr= getArrFromLine("%d"," ",$users);$kmap= [];for($i=0;$i<$users;$i++) {$k= $karr[$i];if(isset($kmap[$k]) && is_array($kmap[$k])) {array_push($kmap[$k],$i+1);}else{$kmap[$k] = [$i+1];}}//print_r($kmap);fscanf(STDIN, "%d",$groups);$res= [];for($i=0; $i<$groups; $i++) {$res[$i] = 0;list($start_id,$end_id,$k) = getArrFromLine("%d"," ",3);if(is_array($kmap[$k])) {foreach($kmap[$k] as$uid) {if($start_id<=$uid&& $uid<=$end_id)$res[$i]++;}}}foreach($resas$r) {echo$r,"\n";}?>
#include <bits/stdc++.h>
using namespace std;
int main(){
int n, q, l, r, k;
scanf("%d", &n);
int a[n+1];
map<int, vector<int>> mp;
for(int i=1;i<=n;i++){
scanf("%d", &a[i]);
mp[a[i]].push_back(i);
}
scanf("%d", &q);
for(int i=0;i<q;i++){
scanf("%d%d%d", &l, &r, &k);
if(mp.find(k) == mp.end())
puts("0");
else{
auto v = mp[k];
auto ll = lower_bound(v.begin(), v.end(), l);
auto rr = upper_bound(v.begin(), v.end(), r);
printf("%ld\n", rr-ll);
}
}
return 0;
} #include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
unordered_map<int,vector<int>> kMapUser;
for (int i = 0; i < n; i++) {
int kValue;
cin >> kValue;
kMapUser[kValue].push_back(i+1); //向量中的元素自动有序,这点很好
}
int q;
cin >> q;
for (int i = 0; i < q; i++) {
int startUserIndex, endUserIndex, kvalue;
cin >> startUserIndex >> endUserIndex >> kvalue;
auto users = kMapUser[kvalue];
auto low = lower_bound(users.begin(), users.end(), startUserIndex);
auto high = upper_bound(users.begin(), users.end(), endUserIndex);
cout << high - low << endl;
}
//system("Pause");
return 0;
} //线段树区间查询(超时)
int layer, sum, first, last; //层数,总结点数,子节点下标起点、终点
int ql, qr, qt; //查询范围的起点终点的真实下标
map<pair<pair<int,int>,int>, int> history; //历史查询记录
//传入元素个数,初始化满二叉树参数,返回总结点数
int init(int n){
sum = 1, layer=1;
int tmp = 1; //满二叉树页节点的个数
while (tmp < n){
tmp *= 2;
sum += tmp;
layer++;
}
sum = sum - tmp + n;
first = pow(2, layer - 1) - 1;
last = first + n -1; //失误:漏了-1
return sum;
}
//i:当前节点下标,返回能到达的叶子节点左边界
int getLeft(int i){
while (i < first){
i = i * 2 + 1;
}
return i;
}
//i:当前节点下标,返回能到达的叶子节点右边界
int getRight(int i){
while (i < first){
i = i * 2 + 2;
}
return i;
}
//查询函数,i:当前节点所在下标
int Query(int i){
if (i >= first){ //叶子节点
if (i >= ql && i <= qr){ //重大失误:没有判断i是否在查询的范围!
return history[{{i, i},qt}];
}
return 0;
}
int lr = getLeft(i);
int rr = getRight(i);
if (rr < ql || lr > qr){ //与查询边界没有交集
return 0;
}
if (lr >= ql && rr <= qr){ //完全包含在查询边界里
if (history.find({ { lr, rr } , qt}) != history.end()){//已有记录
return history[{{lr, rr}, qt}];
}
int total = Query(i * 2 + 1) + Query(i * 2 + 2);
history.insert({ { { lr, rr } ,qt}, total});
return total;
}
return Query(i * 2 + 1) + Query(i * 2 + 2);
}
int main(){
int n;
cin >> n;
init(n);
//为子节点赋值
for (int i = 0; i < n; i++){
int t;
scanf("%d", &t);
history.insert({ { { first + i, first + i }, t }, 1 });
}
//开始查询
cin >> n;
while (n--){
scanf("%d %d %d", &ql, &qr, &qt);
ql = ql + first - 1;
qr = qr + first - 1;
cout << Query(0) << endl;
}
return 0;
} N=int(input())
s=list(map(int,input().split()))
user_dict={} #建立空的dict
for x in range(N):
if user_dict.__contains__(s[x]): #如果包含该key,则直接向value追加数据。value里面是list
user_dict[s[x]].append(x+1)
else:
user_dict[s[x]]=[x+1] #如果不包含该key,添加。
M=int(input())
for x in range(M):
[l,r,k]=list(map(int,input().split())) #边循环,边处理
result = 0
if user_dict.__contains__(k):
for y in user_dict[k]:
if l<=y<=r:
result+=1
print(result) #include <iostream>
#include <vector>
#include <map>
using namespace std;
int main(int argc, char *argv[])
{
int i, j, n, k, l, r, q, input, cnt;
map <int, vector<int> >hobby;
vector<int> tmp;
cin >> n;
for(i = 1; i <= n; i++)
{
cin >> input; //这里输入的就是所有出现的喜好值
if(hobby.count(input) == 0) //如果喜好值没有出现过
{
tmp.clear();//注意这行的作用,因为某次循环中,tmp可能是上一次循环的tmp,即tmp不为空,所以要先清空
tmp.push_back(i);
hobby[input] = tmp;
tmp.clear();
}
else
{
tmp = hobby[input];
tmp.push_back(i);
hobby[input] = tmp; //覆盖原来的键值
}
}
cin >> q;
while(q--)
{
cin >> l >> r >> k;
cnt = 0;
if(hobby.count(k)) //这个喜好值在map中
{
tmp = hobby[k];
j = tmp.size();
for(i = 0; i < j; i++) //计算有多少个用户编号在范围内
{
if(tmp[i] >= l && tmp[i] <= r)
{
cnt++;
}
}
}
cout << cnt << endl;
}
return 0;
}
直接在数组中进行判断有几个的,但是不知道数据大的时候,牛客上怎么就ac了,有点奇怪
import java.util.Scanner;
/**
* @Auther: xuzhangwang
* @Description:
*/
public class Main {
static int[] arr;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
arr = new int[n + 1];
for (int i = 1; i < n + 1; i++) {
arr[i] = sc.nextInt();
}
int q = sc.nextInt();
for (int i = 0; i < q; i++) {
int l = sc.nextInt();
int r = sc.nextInt();
int k = sc.nextInt();
check(arr, l, r, k);
}
}
private static void check(int[] arr, int l, int r, int k) {
int ans = 0;
for (int i = l; i <= r; i++) {
if (arr[i] == k) {
ans++;
}
}
System.out.println(ans);
}
}
#include <stdio.h>int main() {int n, q, low, high, key, cnt, i;scanf("%d", &n);int likes[n];for (i=0; i<n; ++i)scanf("%d", &likes[i]);scanf("%d", &q);while (q--) {cnt = 0;scanf("%d %d %d", &low, &high, &key);for (i=low-1; i<high; ++i)if (likes[i] == key)cnt++;printf("%d\n", cnt);}return 0;}
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n; cin >> n;
vector<int> users(n);
for(int i = 0; i < n; cin >> users[i++]);
int q; cin >> q;
vector<int> l(q), r(q), k(q);
for(int i = 0; i < q; cin >> l[i] >> r[i] >> k[i++]);
map<int, vector<int>> mp;
for(int i = 0; i < n; ++i)
mp[users[i]].push_back(i+1);
vector<int> res(q, 0);
for(int i = 0; i < q; ++i) {
if(mp.count(k[i]) == 0)
continue;
auto pos = mp[k[i]];
auto low = lower_bound(pos.begin(), pos.end(), l[i]);
auto up = upper_bound(pos.begin(), pos.end(), r[i]);
res[i] = up - low;
}
for(int i = 0; i < q; ++i)
cout << res[i] << endl;
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
int q = in.nextInt();
int[][] query = new int[q][3];
for (int i = 0; i < q; i++) {
query[i][0] = in.nextInt();
query[i][1] = in.nextInt();
query[i][2] = in.nextInt();
}
for (int i = 0; i < q; i++) {
int result = 0;
int start = query[i][0] - 1;
int end = query[i][1] - 1;
for(int j = start; j <= end; j++){
if(arr[j] == query[i][2]){
result++;
}
}
System.out.println(result);
}
}
} #include<bits/stdc++.h>
using namespace std;
int main(void){
int n; cin>> n;
int user[n]; memset(user, 0, n*4);
for(int i=0; i<n;i++) cin>> user[i];
int q; cin>> q;
int request[q][3];
for(int i=0; i<q;i++){
for(int j=0; j<3;j++)
cin>> request[i][j];
}
vector<int> res;
for(int i=0; i<q;i++){
int left = request[i][0], right=request[i][1], key = request[i][2];
int num=0;
for(int j=left-1; j<=right-1 ;j++){
if(user[j] == key){
num++;
}
}
res.push_back(num);
}
for(auto it: res) cout<< it<<endl;
return 0;
} 左右指针这道题时间限制不太行啊,我暴力也过了 (1049ms)
#include
using namespace std;
int n, p;
int T[300005];
void solve(int l, int r, int k) {
int cnt = 0;
for(int i = l; i <= r; ++i) {
if(T[i] == k) ++cnt;
}
printf("%d\n", cnt);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &T[i]);
scanf("%d",&p);
for(int i = 0; i < p; ++i) {
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
solve(l, r, k);
}
}再来一个二分的解法,这个不如上面的快(2110ms),应该和测试用例过有关。
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <map>
using namespace std;
int n, q;
int T[300005];
int main() {
scanf("%d", &n);
for(int i = 0; i < n; ++i) {
scanf("%d", &T[i]);
}
map<int, vector<int>> t;
scanf("%d", &q);
for(int i = 0; i < q; ++i) {
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
if(t.find(k) == t.end()) {
t[k] = vector<int>();
for(int i = 0; i < n; ++i)
if(T[i] == k) {
t[k].push_back(i+1);
// cout << "insert " << i << endl;
}
}
auto low = lower_bound(t[k].begin(), t[k].end(), l);
auto up = upper_bound(t[k].begin(), t[k].end(), r);
printf("%d\n", up - low);
}
return 0;
}