方法一:预处理
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
using namespace std;
int c[100005],w[100005],s[100005],t[100005],tmp,N,n,m,k,i,cnt,pos,ans;
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(i=1;i<=m;i++)
scanf("%d",&t[i]);
s[n]=w[n];
tmp=n-1;
cnt=1;
while(s[n]<=k&&tmp>0)
{
s[n]+=w[tmp];
tmp--;
cnt++;
}
c[n]=cnt;
N=n-1;
while(N)
{
s[N]=s[N+1]-w[N+1];
cnt--;
while(s[N]<=k&&tmp>0)
{
s[N]+=w[tmp];
tmp--;
cnt++;
}
c[N]=cnt;
if(tmp<=0)
{
for(i=N;i>0;i--)
c[i]=i;
break;
}
N--;
}
//处理每一个分散注意力的秒
sort(t+1,t+m+1);
t[0]=0;
ans=0;
pos=0;
for(i=1;i<=m;i++)
{
tmp=(t[i]-t[i-1]);
pos+=tmp;
if(pos>n){//时间超出了全部拿完的时间
pos-=tmp;
break;
}
ans+=tmp;
pos=pos-1-c[pos-1];
}
ans+=(n-pos);
printf("%d\n",ans);
}
return 0;
}
方法二:二分
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MM 100000005
#define NN 100005
int n, m, k;
int a[NN], b[NN], sum[MM];
int binary_search(int x)
{
int left = 0, right = n, res = 0;
while(left<=right)
{
int mid=(left+right)/2;
if(sum[mid]<x)
{
res = mid;
left = mid+1;
}
else
right = mid-1;
}
return res;
}
int main()
{
while(scanf("%d%d%d", &n, &m, &k) != EOF)
{
sum[0] = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i = 0; i < m; i++)
scanf("%d", b+i);
b[m]=1234567890;
m++;
int now=0, ans=0, ok;
for(int i = 0; i < m; i++)
{
if(n-now<b[i]-ans)//剩的小于下次分心时间,直接全拿了
{
ans+=n-now;
break;
}
else
{
ok=b[i]-ans+now;//现在有的石头
ans=b[i];
now=binary_search(sum[ok-1]-k);//ok-1是因为这一分钟不能拿石头,二分查找当前能拥有的数量
}
}
printf("%d\n",ans);
}
return 0;
}