1.对于一个从小到大排序的数组,lower_bound(begin,end,x) 查找成功返回的是从地址begin到end-1中第一个大于或者等于x的地址,减去begin恰好为数组下标。查找失败返回end。
2.对于一个从小到大排序的数组,upper_bound(begin,end,x) 查找成功返回的是从地址begin到end-1中第一个大于x的地址,减去begin恰好为数组下标。查找失败返回end。
3.对于一个从大到小排序的数组,lower_bound(begin,end,x,greater < int >()) 查找成功返回的是从地址begin到end-1中第一个小于或者等于x的地址,减去begin恰好为数组下标。查找失败返回end。
4.对于一个从大到小排序的数组,upper_bound(begin,end,x,greater< int >()) 查找成功返回的是从地址begin到end-1中第一个小于x的地址,减去begin恰好为数组下标。查找失败返回end。
5.upper_bound和lower_bound查找是通过二分查找的,所以查找序列必须是排好序的。
#include
#include
#include
using namespace std;
int a[5]={0,1,1,2,3};
vector<int> v={0,1,1,2,3};
int main()
{
int ans=0;
ans=lower_bound(a,a+5,1)-a;
cout<<ans<<endl;//1
ans=upper_bound(a,a+5,1)-a;
cout<<ans<<endl;//3
ans=lower_bound(a,a+5,4)-a;
cout<<ans<<endl;//5
ans=upper_bound(a,a+5,4)-a;
cout<<ans<<endl;//5
ans=lower_bound(v.begin() ,v.end() ,1)-v.begin();
cout<<ans<<endl;//1
ans=upper_bound(v.begin() ,v.end() ,1)-v.begin();
cout<<ans<<endl;//3
ans=lower_bound(v.begin() ,v.end() ,4)-v.begin() ;
cout<<ans<<endl;//5
ans=upper_bound(v.begin() ,v.end() ,4)-v.begin() ;
cout<<ans<<endl;//5
//a[5]={3,2,1,1,0}
sort(a,a+5,greater<int>());
ans=lower_bound(a,a+5,1,greater<int>())-a;
cout<<ans<<endl;//2
ans=upper_bound(a,a+5,1,greater<int>())-a;
cout<<ans<<endl;//4
ans=lower_bound(a,a+5,4,greater<int>())-a;
cout<<ans<<endl;//0
return 0;
}
Range Count Query
时间限制: 2.000 Sec 内存限制: 1024 MB
题目描述
You are given a sequence of length N: A=(A1,…,AN).Answer Q queries given in the following format.
You are given integers L, R, and X.
Find the number of elements among AL, …, AR whose values are equal to X.
Constraints
1 ≤ N ≤ 2× 105
1 ≤ Ai ≤ N
1 ≤ Q ≤ 2× 105
1≤L ≤ R ≤ N, 1 ≤ X ≤ N, for each query.
All values in input are integers.
输入
Input is given from Standard Input in the following format:
N
A1 A2 … AN
Q
Query1
Query2
.
.
.
QueryQ
输出
Print Q lines, the i-th of which contains the answer to the i-th query.
样例输入 Copy
【输入样例1】
5
3 1 4 1 5
4
1 5 1
2 4 3
1 5 2
1 3 3
样例输出 Copy
【输出样例1】
2
0
0
1
提示
【样例1解释】
In the first query, two of (A1,A2,A3,A4,A5)=(3,1,4,1,5) have values equal to 1.
In the second query, zero of (A2,A3,A4)=(1,4,1) have values equal to 3.
题目大意就是在数组a中寻找下标l到r元素中有多少个跟x相等,直接求显然会超时,于是可以开一个vector数组,v[x]里面存放数组a中跟x相等的元素下标值,每次查找的时候找到v[x]中>=l&&<=r有多少个元素即可。
#include
#include
#include
using namespace std;
const int N=2e5+10;
vector<int>v[N];
int main()
{
int n;cin>>n;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
v[x].push_back(i);
}
int q;cin>>q;
while(q--)
{
int ll,rr,x;scanf("%d%d%d",&ll,&rr,&x);
//大于等于ll的元素下标位置
int i1=lower_bound(v[x].begin() ,v[x].end() ,ll)-v[x].begin() ;
//大于rr的元素下标位置
int i2=upper_bound(v[x].begin() ,v[x].end() ,rr)-v[x].begin() ;
//相减即区间内元素个数
int ans=i2-i1;
printf("%d\n",ans);
}
return 0;
}
Auto-Complete
时间限制: 1.000 Sec 内存限制: 64 MB
题目描述
Bessie the cow has a new cell phone and enjoys sending text messages,although she keeps making spelling errors since she has trouble typing on such a small screen with her large hooves. Farmer John has agreed to help her by writing an auto-completion app that takes a partial word and suggests how to complete it.
The auto-completion app has access to a dictionary of W words, each consisting of lowercase letters in the range a…z, where the total number of letters among all words is at most 1,000,000. The app is given as input a list of N partial words (1 <= N <= 1000), each containing at most 1000 lowercase letters. Along with each partial word i, an integer K_i is also provided, such that the app must find the (K_i)th word in alphabetical order that has partial word i as a prefix. That is, if one ordered all of the valid completions of the ith partial word, the app should output the completion that is (K_i)th in this sequence.
输入
10 3
dab
ba
ab
daa
aa
aaa
aab
abc
ac
dadba
4 a
2 da
4 da
样例输出 Copy
3
1
-1
提示
The completions of a are {aa,aaa,aab,ab,abc,ac}. The 4th is ab, which is listed on line 3 of the dictionary. The completions of da are {daa,dab,dadba}. The 2nd is dab, listed on line 1 of the dictionary. There is no 4th completion of da.
题目大意是对于每次查找k和string t,找到题目所给字典里以t为前缀的单词里第k个单词,输出该单词在原字典中的位置。
先用pair保存下来字典,以及string的位置,然后根据字典序对string进行排序,lower_bound函数进行查找第一个以t为前缀的字符串在排序后的pair数组中所在的位置,加上k-1即所查找的字符串所在位置,最后判断一下该位置是否合法即可:
#include
#include
using namespace std;
const int N=10010;
pair<string,int>s[N];
int check(string l,string r)//判断r是不是l的前缀
{
if(r.size() >l.size() ) return 0;
return l.substr(0,r.size() )==r;
}
int main()
{
int w,n;cin>>w>>n;
for(int i=0;i<w;i++)
{
cin>>s[i].first ;
s[i].second =i+1;
}
sort(s,s+w);
while(n--)
{
int k;string t;
cin>>k>>t;
int i=k-1+lower_bound(s,s+w,pair<string,int>(t,0))-s;
if(i>=w||!check(s[i].first ,t))puts("-1");
else printf("%d\n",s[i].second );
}
return 0;
}
无需写出型别, 就可以生成一个pair对象
例:
make_pair(t,0);
而不必费力写成:
pair(t,0); 当有必要对一个接受pair参数的函数传递两个值时, make_pair()尤其显得方便,
void f(make_pair(t,0));
pair 默认对first升序,当first相同时对second升序;