思路1:最直观的想法是,暴力求解。使用likes数组存储用户爱好值,使用search函数求解[l,r]区间内爱好值为k的用户数。每一组均调用search(likes,l,r,k)并输出返回值res。(暴力居然过啦)

#include<bits/stdc++.h>
using namespace std;
//存储用户爱好值
int likes[300005];
int search(int likes[], int l, int r, int k) {
    int res = 0;
    for (int i = l; i <= r; i++) {
        if (likes[i] == k)
            res++;
    }
    return res;
}
int main() {
    //n为用户个数
    int n;
    cin >> n;
    //x为爱好值
    int x;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        likes[i] = x;
    }
    //num表示组数
    int num;
    cin >> num;
    //l表示左边界 r表示右边界 k表示爱好值
    int l, r, k;
    for (int i = 1; i <= num; i++) {
        cin >> l >> r >> k;
        int res = search(likes, l, r, k);
        cout << res<<endl;
    }
}

思路2:最直观的想法是,map。使用likes存储用户爱好值,使用l存储每组左边界,使用r存储每组右边界,使用k存储每组爱好值,使用mp存储(爱好值,用户列表),使用res存储结果。根据组数循环求解结果:首先取出该组爱好值对应的用户列表,由于按照顺序依次加入,且map有序,故用户列表有序;然后使用upper_bound求解第一个大于r的下标,使用lower_bound求解第一个大于等于l的下标,两者相减即为满足用户下标[l,r]且爱好值为k的用户个数。

#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
int main() {
    //n为用户个数
    int n;
    cin >> n;
    //存储用户爱好值
    vector<int> likes(n+1);
    //x为爱好值
    int x;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        likes[i] = x;
    }
    //num表示组数
    int num;
    cin >> num;
    //l表示左边界 r表示右边界 k表示爱好值
    vector<int> l(num+1),r(num+1),k(num+1);
    for (int i = 1; i <= num; i++) {
        cin >> l[i] >> r[i] >> k[i];
    }
    //存储用户喜爱度与用户下标
    map<int,vector<int>> mp;
    for(int i=1;i<=n;i++){
        mp[likes[i]].push_back(i);
    }
    //存储结果
    vector<int> res(num+1,0);
    //根据组数循环结果
    for(int i=1;i<=num;i++)
    {
        //如果喜好度用户数不为0
        if(mp.count(k[i])!=0)
        {
            //提取喜好度用户列表
            auto people = mp[k[i]];
            //lower_bound(起始地址,结束地址,要查找的值)
            //返回第一次出现大于等于x的地址
            //upper_bound(起始地址,结束地址,要查找的值)
            //返回第一个大于x的地址
            res[i]=upper_bound(people.begin(), people.end(), r[i])-lower_bound(people.begin(), people.end(), l[i]);
            //数组必须递增才能使用upper_bound和lower_bound
            //upper_bound(people.begin(), people.end(), r[i])-people.begin()得到对应的下标
            // cout<<"upper:"<<upper_bound(people.begin(), people.end(), r[i])-people.begin()<<";lower:"<<lower_bound(people.begin(), people.end(), l[i])-people.begin()<<endl;
        }
    }
    for(int i=1;i<=num;i++)
        cout<<res[i]<<endl;
}

总结:注意,数组必须有序才可以使用lower_bound和upper_bound。lower_bound(起始地址,结束地址,要查找的值x) ,返回的是在数组中插入x并且插入后仍保持有序的最小的可以插入的位置;lower_bound(起始地址,结束地址,要查找的值x) -起始地址,返回的是第一次出现大于等于x的下标;upper_bound(起始地址,结束地址,要查找的值x) ,返回的是在数组中插入x并且插入后仍保持有序的最大的可以插入的位置;upper_bound(起始地址,结束地址,要查找的值x) -起始地址,返回的是第一个大于x的下标。