题目大意
给出一个数组,现在每个数的贡献为该数前面大于该数的最小值,求数组所有数的累积贡献。
解题思路
首先用 s e t set set维护升序,接着二分查找前面第一个比它大的数, s e t set set里自带了 a l g o r i t h m algorithm algorithm里的 l o w e r _ b o u n d lower\_bound lower_bound和 u p p e r _ b o u n d upper\_bound upper_bound,直接使用 u p p e r _ b o u n d upper\_bound upper_bound查找即可,如果没找到会返回 s e t : : e n d ( ) set::end() set::end()迭代器,判断一下即可
拓展一下这道题,它还能应用于求每个数前面比它大的最大值;每个数前面比它小的最大值;每个数前面比它小的最小值。而本题是每个数前面比它大的最小值。
前缀较大的最小值
复习一下 l o w e r _ b o u n d ( ) lower\_bound() lower_bound()和 u p p e r _ b o u n d ( ) upper\_bound() upper_bound()
//在set中直接传要查询的元素即可
lower_bound(val); //查找大于等于val第一个元素的位置,没有找到返回set::end()
upper_bound(val); //查找大于val第一个元素的位置,没有找到返回set::end()
#include <iostream>
#include <set>
using namespace std;
typedef long long ll;
int main(){
int n,x;
ll ans=0;
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
set<int> s;
cin>>n;
while(n--){
cin>>x;
s.insert(x);
auto i=s.upper_bound(x);
if(i!=s.end()){
ans+=*i;
}
}
cout<<ans<<endl;
return 0;
}
前缀较大的最大值
这里再补充一下几个迭代器分别返回容器的什么位置
begin(); //容器第一个元素的位置
end(); //容器最后一个元素的下一个位置,也就是容器遍历的结束标志,此位置不可访问
rbegin(); //容器逆向的第一个元素,也就是最后一个元素的位置
rend(); //第一个元素的前一个位置
#include <iostream>
#include <set>
using namespace std;
typedef long long ll;
int main(){
int n,x;
ll ans=0;
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
set<int> s;
cin>>n;
cin>>x;
s.insert(x);
n--;
while(n--){
cin>>x;
auto it=s.rbegin(); //不能"auto it=s.end()-1;"会报错
//auto it =s.end(); it--;
if(x<*it) ans+=*it;
s.insert(x);
}
cout<<ans<<endl;
return 0;
}
前缀较小的最大值
#include <iostream>
#include <set>
using namespace std;
typedef long long ll;
int main(){
int n,x;
ll ans=0;
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
set<int> s;
cin>>n;
while(n--){
cin>>x;
s.insert(x);
auto it=s.lower_bound(x);
if(it!=s.begin() && it!=s.end()){ //两边都要考虑,begin是因为可能找不到,end是因为可能都比查找值小
it--;
ans+=*it;
}
}
cout<<ans<<endl;
return 0;
}
前缀较小的最小值
#include <iostream>
#include <set>
using namespace std;
typedef long long ll;
int main(){
int n,x;
ll ans=0;
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
set<int> s;
cin>>n;
cin>>x;
s.insert(x);
n--;
while(n--){
cin>>x;
auto it=s.begin();
if(x>*it){
ans+=*it;
}
s.insert(x);
}
cout<<ans<<endl;
return 0;
}