用户喜好
题目难度:中等
知识点:二分查找,STL,vector,map
解题思路:
1.输入人数,根据人数建立喜好度vector user(n)。
2.输入查询组数,根据组数建立左右区间数字l和r,以及查询喜好度数字k的vector。
3.建立喜好度与用户标号之间的对应关系map<int,vector< int > >,这里的第一个参数是喜好度数值,第二个参数vector<int>是该喜好度对应的用户标号。如题例中喜好度为1时,该vector中保存[1];喜好度为3时,该vector中保存[3,4]。
4.开始查询。根据k[i]中的喜好度查询数值,可以找到map中该喜好度对应的vector p。使用二分查找,可以在p中找到第一个大于等于l[i]的位置,以及第一个大于r[i]的位置。将两个位置相减即为所求人数,保存到res中。如题例所示,输入查询组数为:</int>
1 2 1 2 4 5 3 5 3
- 当查询1 2 1这一组时,k[i]=1,l[i]=1,r[i]=2。根据k[i]从map中获得喜好度为1的vector p,它是[1]。那么lower_bound(p.begin(),p.end(),1)会返回一个指向1的迭代器,upper_bound(p.begin(),p.end(),2)会返回一个p.end()的迭代器,这时两个迭代器相减得1,输出1。
- 当查询2 4 5这一组时,k[i]=5,l[i]=2,r[i]=4。根据k[i]从map中获得喜好度为5的vector p,它是[5]。那么lower_bound(p.begin(),p.end(),2)会返回一个指向5的迭代器,upper_bound(p.begin(),p.end(),4)也会返回一个指向5的迭代器,这时两个迭代器相减得0,输出0。
- 当查询3 5 3这一组时,k[i]=3,l[i]=3,r[i]=5。根据k[i]从map中获得喜好度为3的vector p,它是[3,4]。那么lower_bound(p.begin(),p.end(),3)会返回一个指向3的迭代器,upper_bound(p.begin(),p.end(),5)会返回一个p.end()的迭代器,这时两个迭代器相减得2,输出2。
#include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; class solution { public: void func() { int n,q; cin>>n; //输入人数 vector<int> user(n); for(int i=0;i<n;i++) cin>>user[i]; //录入喜好度 cin>>q; //查询组数 vector<int> l(q),r(q),k(q); for(int i=0;i<q;i++) cin>>l[i]>>r[i]>>k[i]; //查询区间起点l,终点r,喜好度k map<int,vector<int> > mp; for(int i=0;i<n;i++) mp[user[i]].push_back(i+1); //每个喜好度对应用户的标号存入vector与喜好度对应(注意下标+1) vector<int> res(q,0); //结果 for(int i=0;i<q;i++) //根据组数循环得到结果 { if(mp.count(k[i])!=0) //如果该喜好度用户数不为0 { vector<int> p = mp[k[i]]; //提出该喜好度对应用户标号的vector //二分查找 //lower_bound(起始地址,结束地址,要查找的数值x) //返回的是第一次出现大于等于x的地址 //upper_bound(起始地址,结束地址,要查找的数值x) //返回的是第一个大于x的地址 //从p中找到≤r[i]的位置减去≥l[i]的位置,即为结果所求人数。 res[i] = upper_bound(p.begin(), p.end(), r[i]) - lower_bound(p.begin(), p.end(), l[i]); } } for(int i = 0; i < q; ++i) cout << res[i] << endl; } };