EOJ Monthly 2018.9 (based on Trial Round #3) E.双人旋转赛车(二分+(贪心/单指针/线段树/主席树))

编程入门 行业动态 更新时间:2024-10-13 00:34:02

EOJ Monthly 2018.9 (based on Trial Round #3) E.双人旋转赛车(二分+(贪心/单指针/<a href=https://www.elefans.com/category/jswz/34/1769188.html style=线段树/主席树))"/>

EOJ Monthly 2018.9 (based on Trial Round #3) E.双人旋转赛车(二分+(贪心/单指针/线段树/主席树))

题目

oxx 和 Xiejiadong 在玩一个双人旋转赛车的小游戏。

他们将进行一些比赛。每局比赛必须按顺序进行,胜者会得到该局对应的分数 xi。

由于 oxx 技艺不精(每局都可以由 Xiejiadong 决定胜负),

因此他给自己设置了初始分数 k,希望自己能够一直领先 Xiejiadong。

不过 Xiejiadong 识破了 oxx 的诡计,现在 Xiejiadong 想知道自己至少需要赢几局才可以使得自己能够在某一时刻的比分不落后于 oxx。

若无法达到则输出 −1。

n<=1e6,k<=1e9,1<=xi<=1e9

思路来源

/?tdsourcetag=s_pctim_aiomsg

题解

题解写的够优秀了,我就不BB了,直接粘代码

代码1(解法2:单指针,O(nlogn))

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int maxn=1e6+10; 
int n,k,Rank[maxn];
int tmp[maxn];//临时储存数量 
int pointer,now;//指针(pointer,n] 当前k个值都在后面 
int l,r;
struct node
{int a,id,rk;
}e[maxn];
bool operator<(node a,node b)
{return a.a<b.a||(a.a==b.a&&a.id<b.id);
}
bool cmp(node a,node b)
{return a.id<b.id;
}
bool ok(int mid,int k) 
{//printf("mid:%d\n",mid);ll sum=0,score=k;pointer=now=0;memset(tmp,0,sizeof tmp); for(int i=1;i<=n;++i){if(e[i].rk>pointer&&now<=mid){tmp[e[i].rk]++;now++;sum+=Rank[e[i].rk];}else score+=Rank[e[i].rk];while(now>mid&&pointer<n){pointer++;if(tmp[pointer]){tmp[pointer]--;now--;score+=Rank[pointer];sum-=Rank[pointer];}}//printf("rk:%d v:%lld\n",e[i].rk,e[i].a);//printf("sum:%lld score:%lld\n",sum,score);if(sum>=score)return 1;}return 0;
}
int main()
{scanf("%d%d",&n,&k);for(int i=1;i<=n;++i){scanf("%d",&e[i].a);e[i].id=i;}sort(e+1,e+n+1);for(int i=1;i<=n;++i){e[i].rk=i;Rank[i]=e[i].a;}sort(e+1,e+n+1,cmp);l=0;r=n;while(l<r){int mid=(l+r)/2;if(!ok(mid,k))l=mid+1;else r=mid;}if(!ok(l,k))puts("-1");else printf("%d\n",l);return 0;
} 

代码2(解法3:贪心)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn=1e6+10; 
//贪心 每次把最小的还给oxx 
//优先队列表示在队列中的 是xiejiadong要选的 
priority_queue<ll,vector<ll>,greater<ll> >q; 
ll sum1,sum2,a[maxn];
int n,now,ans;
int main()
{scanf("%d%lld",&n,&sum1);for(int i=1;i<=n;++i)scanf("%lld",&a[i]);ans=n+1;for(int i=1;i<=n;++i){sum2+=a[i]; q.push(a[i]);now++;//now=q.size()while(sum2-q.top()>=sum1+q.top()){sum2-=q.top();sum1+=q.top();q.pop();now--;}if(sum2>=sum1)ans=min(ans,now); }printf("%d\n",ans==n+1?-1:ans);return 0;
} 

代码3(解法4:树状数组)

 

代码4(解法5:主席树)

更多推荐

EOJ Monthly 2018.9 (based on Trial Round #3) E.双人旋转赛车(二分+(贪心/单指针/线段树/主席树))

本文发布于:2024-02-24 15:55:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1695841.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:线段   双人   指针   贪心   主席

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!