问题描述
洛洛和晶晶计划一起挑战峡谷深渊,这个深渊有两个入口,分别为左边和右边。左边的入口有 n 个关卡,第 i 个关卡需要消耗 ai 块能源紫水晶。右边的入口有 m 个关卡,第 ii 个关卡需要消耗 bi 块能源紫水晶。为了挑战下一个关卡,两个入口的关卡必须按顺序通过。
洛洛决定选择左边的入口,而晶晶决定选择右边的入口。两人总共只携带了 k 块能源紫水晶。他们不确定如何分配能源才能使得通过的关卡数之和最大。你需要帮助他们求出通过的关卡数之和的最大值。请注意,你无需给出具体的能源分配方案,只需要计算可以达到的最大关卡数之和。
输入格式
第一行输入三个整数 n,mm,k 。
第二行输入 n 个整数 ai 。
第三行输入 m 个整数 bi 。
数据范围保证:1≤n,m≤2×105,1≤ai,bi,k≤109.
输出格式
输出一个整数,表示两人通过的关卡数之和最大值。
样例输入
2 2 10
1 2
3 5
样例输出
3
说明
样例中洛洛通过 2 关,晶晶通过 1 关,总共可通过 3 关。
初期想法:(过了1/4)
#include <bits/stdc++.h>
using namespace std;
int n, m, k;
int main() {
cin >> n >> m >> k;
int a[n];
int b[n];
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= m; i++) {
cin >> b[i];
}
int s = 0;
int w;
int i = 1, j = 1;
while (k>0) { //当还有能量的时候执行
s++;//闯关数增加
if(i>n &&j<=m)//如果a的关卡闯完了,但b没有
{
w=b[j];
}
else if(i<=n && j>m)//b没有,a完了
{
w=a[j];
}
else w = min(a[i], b[j]);
if (w == a[i] && i <= n) {
i++;
} else if (w == b[j] && j <= m) {
j++;
}
k -= w;
if (k <= 0 ||(i==n+1 && j==m+1)) {
break;
}
}
if (k < 0) {//多了一次
s--;
}
cout << s << endl;//当k=0时刚好
return 0;
}
为什么错呢?因为我只比较两个数据没有比较全局:
假设:
a:2 5 1 1 1 1
b:3 4 2 2 2 2 它会一直比较5和2的大小忽略了5+1+1+1+1<4+2+2+2+2.没有考虑周全.
中期:只有前缀和的做法 (过了)
#include<bits/stdc++.h>
using namespace std;
long long int a[200005];
long long int b[200005];
int n,m,k,ans,sum;
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1];//前缀和
}
for(int i=1;i<=m;i++)
{
cin>>b[i];
b[i]+=b[i-1];
}
for(int i=n;i>=0;i--)
{
while(a[i]+b[sum]<=k and sum<=m)
{
ans=max(ans,sum+i);
sum++;
}
if(sum>m)
{
break;
}
}
cout<<ans;
return 0;
}
最后加上二分的想法 (过了)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N],b[N];
ll n,m,k;
ll check(ll mid){//mid为通过关卡数
ll ans=k+1;
for(int i=0;i<=mid;i++){
if(i>n||mid-i>m)continue; //不能让a,b越界
ans=min(ans,a[i]+b[mid-i]);
}
return ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]+=a[i-1];
}
for(int i=1;i<=m;i++){
cin>>b[i];
b[i]+=b[i-1];
}
ll l=0,r=n+m+1;
while(l<r){
ll mid=(l+r)>>1;
if(check(mid)>k) r=mid;
//这里的mid代表通关数通关mid次需要多少快能源紫水晶
else l=mid;
}
cout<<l;
return 0;
}