思路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的下标。