T1
题目描述
给定一个圆形蛋糕,被 nnn 条切割线分成 nnn 个扇形蛋糕块,按照顺时针编号,第 iii 块上有 aia_iai 个草莓,第 iii 条切割线到第 i+1i+1i+1 条切割线之间的部分是第 iii 块蛋糕。
Alice 和 Bob 流选择切割线,假设 Alice 选择了第 iii 条切割线,Bob选择了第 jjj 条切割线,jjj 不能等于 iii。则 Alice 获得从第 iii 条切割线顺时针到第 jjj 条切割线之间的蛋糕,Bob获得剩余蛋糕。Alice 的平均草莓数若大于等于 Bob 的平均草莓数,则 Alice 获胜,否则 Bob 获胜。求使 Alice 必胜的最小切割线编号,不存在则输出 −1-1−1。
输入格式
第一行一个正整数 nnn
。
第二行 nnn 个正整数 aia_iai 表示第 iii 块内的草莓数量。
输出格式
一个整数,即为答案。
样例
样例输入1
3
3 8 5
样例输出1
2
Alice 在 333 和 888 之间切一刀,Alice要么会拿到 888 要么会拿到 888 和 555,都可以获胜。
数据范围
对于所有数据 1<n≤500000,1≤ai≤5000001<n≤500000,1≤ai≤5000001<n≤500000,1≤ai≤500000。
对于 50%50 \%50% 的数据 n≤1000n≤1000n≤1000。
对于 100%100 \%100% 的数据无特殊限制。
解法说明
可将每个 aia_iai 转化为其与所有数字的平均值之间的差,对新的 aia_iai 做前缀和,则当 Alice 选 iii,Bob 选 jjj 时,如 sumj−1−sumi−1≥0sum_{j-1} - sum_{i-1} ≥ 0sumj−1−sumi−1≥0,则 Alice 胜。故 Alice 应选 sumi−1sum_{i-1}sumi−1 最小的点后面的切割线,此时无论 Bob 如何选择都必败。
通过代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+10;
namespace IO{
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') f=(ch=='-'?-1:f),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
}using namespace IO;
namespace code{
int n,a[N],sum[N],ans;
void solve(){
n=read();
for(int i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
for(int i=1;i<=n;i++) a[i]=a[i]*n-sum[n];
for(int i=1;i<n;i++) sum[i]=sum[i-1]+a[i],ans=(sum[i]<sum[ans]?i:ans);
write(ans+1);
}
}
signed main(){
code::solve();
return 0;
}
T2
题目描述
游乐园有 nnn 个项目,第 iii 个项目直接排队要 aia_iai 分钟,使用优速通需要排队 bib_ibi 分钟。你有 kkk 张优速通票,也就是意味着你可以选不超过 kkk 个项目使用优速通。你一共有 ttt 分钟,这里忽略除了排队以外的其他时间。你想知道你最多可以玩多少个不同的项目。
输入格式
第一行三个正整数 nnn,kkk,ttt。
接下来 nnn 行,每行两个正整数 aia_iai,bib_ibi。
输出格式
一个整数,即最多能玩的项目数量。
样例
样例输入1
5 2 20
7 4
10 8
3 3
8 7
9 5
样例输出1
4
数据范围
对于所有数据 1≤k≤n≤2×105,1≤T≤1018,1≤bi≤ai≤10121≤k≤n≤2×10^5,1≤T≤10^{18}, 1≤b_i≤a_i≤10^{12}1≤k≤n≤2×105,1≤T≤1018,1≤bi≤ai≤1012
。
对于 20%20\%20% 的数据:n≤10n≤10n≤10。
对于 50%50\%50% 的数据:n≤1000n≤1000n≤1000。
对于 100%100\%100% 的数据:无特殊限制。
解法说明
反悔贪心。
显然,前 kkk 个肯定是 bib_ibi 能选几个是几个。如果选完后 t>0t>0t>0,则应增加一些项目,有以下两种可能:
- 新加一个 aia_iai
- 新加一个 bib_ibi,并将一个选过的 bjb_jbj 换成 aja_jaj。
此时我们可以开三个堆,一个存储未选过的 aia_iai,另一个存储未选过的 bib_ibi,最后一个存储选过的 aj−bja_j - b_jaj−bj。记三个堆堆顶分别为 uuu、vvv、www,则如果 u<v+wu<v+wu<v+w 选择第一种,否则选择第二种,不停循环直到 t<0t<0t<0 为止。
通过代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
#define mp make_pair
const int N=2e5+10;
namespace IO{
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') f=(ch=='-'?-1:f),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
}using namespace IO;
namespace code{
int n,k,t,ans;
bool vis[N];
struct node{
int a,b;
}a[N];
priority_queue<PII,vector<PII>,greater<PII> > q1,q2,q3;
bool cmp(node x,node y){
return x.b<y.b;
}
void solve(){
n=read(),k=read(),t=read();
for(int i=1;i<=n;i++) a[i].a=read(),a[i].b=read();
sort(a+1,a+n+1,cmp);
for(int i=1;i<=k&&t>=0;i++,ans++) t-=a[i].b,vis[i]=1;
if(t<0) return write(ans-1),void();
for(int i=1;i<=n;i++){
if(!vis[i]) q1.push(mp(a[i].a,i)),q2.push(mp(a[i].b,i));
else q3.push(mp(a[i].a-a[i].b,i));
}
while(t>0){
int x=q1.top().second,y=q2.top().second,u,v,w;
while(vis[x]) q1.pop(),x=q1.top().second;
while(vis[y]) q2.pop(),y=q2.top().second;
ans++,u=q1.top().first,v=q2.top().first,w=q3.top().first;
if(u<v+w) q1.pop(),vis[x]=1,t-=u;
else q2.pop(),q3.pop(),vis[y]=1,t-=v+w,q3.push(mp(a[y].a-a[y].b,y));
}
write(t<0?--ans:ans);
}
}
signed main(){
code::solve();
return 0;
}
1719

被折叠的 条评论
为什么被折叠?



