2020牛客国庆集训派对day3 Leftbest

Leftbest
链接:https://ac.nowcoder.com/acm/contest/7830/A
来源:牛客网

题目描述

Jack is worried about being single for his whole life, so he begins to use a famous dating app. In this app, the user is shown single men/women’s photos one by one, and the user may choose between “yes” and “no”. Choosing “yes” means an invitation while choosing “no” means nothing. The photos would be shown one by one until the number of rest photos to be shown reaches zero. Of course, efficient and single Jack would always choose “yes”.

When viewing photos, Jack would have a “fake impression point” on every photo, which is not accurate. To calculate the “true impression point” of one photo, Jack would recall the “fake impression point” of every previous photo whose “fake impression point” is larger than this photo, and regard the smallest “fake impression point” of them as the “true impression point” of this photo. Jack would like to sum the “true impression point” of all photos as the outcome of his effort.

Note that if such a larger “fake impression point” does not exist, the “true impression point” of this photo is zero.
输入描述:
The first line contains an integer {n}n (1 \le n \le 100,0001≤n≤100000) — the number of photos.
The second line contains n integers is the “fake impression point” of the i-th photo.
输出描述:
Output a single integer — the sum of the “true impression point” of all photos.
示例1
输入
复制

4 2 1 4 3

输出
复制

6

题意:

排在a[i]前面 比a[i]大的数中最小数的和是多少?

题解:

第一反应是用大小堆来做,思路很简单,但是却超时了。。
后来想起来set里面本身就是函数是用来求这个的

lower_bound(val);        //查找大于等于val第一个元素的位置,没有找到返回set::end()

upper_bound(val);        //查找大于val第一个元素的位置,没有找到返回set::end()

所以直接
j=s.upper_bound(x)就行
STL有好多现成的东西,太久没用都忘得差不多了

代码:

一开始大小堆的代码:

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1e5+8;
int a[maxn];
typedef long long ll;
priority_queue<int,vector<int>,less<int> >q;//从小到大 
priority_queue<int,vector<int>,greater<int> >w;//从大到小 
int main()
{
   
	ios::sync_with_stdio(false);
	int n;
	scanf("%d",&n);
	ll sum=0;
	for(int i=1;i<=n;i++)
	{
   
		int x;
		scanf("%d",&x);
		
		while(!q.empty())
		{
   
		// printf("q.top=%d\n",q.top());
			//cout<<"q.top="<<q.top<<endl;
			if(q.top()>x)
			{
   
				w.push(q.top());
				q.pop();
			}
			else break;
		}
		if(!w.empty())
		sum+=w.top();
		while(!w.empty())
		{
   
			q.push(w.top());
			w.pop();
		} 
		q.push(x);

	}
	cout<<sum;
	return 0;
}

AC代码:

#include<cstdio>
#include<iostream>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=1e5+8;
set<int>s;
typedef long long ll;
int main()
{
   
	ios::sync_with_stdio(0);
	int n;
	cin>>n;
	ll sum=0;
	while(n--){
   
		int x;
		cin>>x;
		s.insert(x);
		auto j=s.upper_bound(x);
		if(j!=s.end())sum+=*j;

	}
	cout<<sum;
	return 0;
}

扩展

刚才那个题求的是前缀较大的最小值
我们扩展到其他几个
注意:
set在内部会自动排序,且会自动查重(即每个数最多出现一次)

前缀较大的最大值

#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;
}

全部评论

相关推荐

刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
02-18 13:28
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务