列表

详情


NC207576. SumoandRobotGame

描述

Sumo正在参加一个机器人比赛,这个比赛的规则是这样的:在一个一维坐标轴上操控一个初始位置为0的机器人,机器人每次只能向左或者向右移动一个单位距离。每位参赛者都需要上传一个长度恰好为x的仅由‘L’和‘R’组成的执行序列,‘L’表示向左移动,‘R’表示向右移动(例如“LRLLR”即为长度为5的执行序列,机器人的运动轨迹为-1,0,-1,-2,-1),随后测试系统会严格按照执行序列给出的命令顺序模拟机器人的行动。

在坐标轴上分布着n个得分点(由正数给出)或扣分点(由负数给出),当机器人第一次到达某个得分点或扣分点时,它会获得或扣去相应的分数(初始分数为0),在每个人的执行序列执行完毕后系统会给出最终得分。

Sumo想让你帮助他设计一个执行序列来获得尽可能多的分数,由于序列可能过长,因此你只需要告诉Sumo最多能拿到多少分数。

输入描述

第一行包含两个整数 ,表示一共有n个得分点或扣分点,表示执行序列的长度。

第二行给出n个整数表示第i个点在轴上的位置,且

第三行给出n个整数正数表示得分点,负数表示扣分点,其绝对值表示当第一次到达该点时所应获得或扣去的分数值。

输出描述

输出一个整数代表Sumo有可能得到的的最大分数。

示例1

输入:

6 6
-3 -2 -1 1 2 3
1 -1 4 5 1 4

输出:

14

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 60ms, 内存消耗: 14316K, 提交时间: 2020-06-06 16:49:39

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1e5+10;
int n,t;
long long v[maxn],sum,f[22][maxn],ans,p[maxn],k;
long long ck(int ll,int rr)
{
	int kk=0; while ((1<<(kk+1))<(rr-ll+1)) kk++;
return max(f[kk][ll],f[kk][rr-(1<<kk)+1]);
}
int main()
{
	scanf("%d%lld",&n,&k); t=-1;
	for (int i=1;i<=n;i++) 
	{
		scanf("%lld",&p[i]);
		if (p[i]>0 && t==-1) t=i;
	}
	for (int i=1;i<=n;i++) scanf("%lld",&v[i]);
	if (t==-1)
	{
		sum=0;
		for (int i=n;i>=1;i--) 
		{
			sum+=v[i];
			if (abs(p[i])<=k) ans=max(ans,sum);
		}
		printf("%lld\n",ans);
		return 0;
	}
	if (t==1)
	{
		sum=0;
		for (int i=1;i<=n;i++) 
		{
			sum+=v[i];
			if (abs(p[i])<=k) ans=max(ans,sum);
		}
		printf("%lld\n",ans);
		return 0;
	}
	ans=-1e18;
	if (p[t]-1!=0) ans=0;
	if (p[t-1]+1!=0) ans=0;
	sum=0;
	for (int i=t;i<=n;i++) 
	{
		sum+=v[i]; f[0][i]=sum;
		if (p[i]<=k) ans=max(ans,sum);
	}
	sum=0;
	for (int i=t-1;i>=1;i--)
	{
		sum+=v[i]; f[0][i]=sum;
		if (abs(p[i])<=k) ans=max(ans,sum);
	}
	for (int j=1;(1<<j)<=n;j++)
	 for (int i=1;i+(1<<j)-1<=n;i++)
	  f[j][i]=max(f[j-1][i],f[j-1][i+(1<<(j-1))]);
	for (int i=1;i<t;i++)
	if (2ll*abs(p[i])<=k)
	{
		long long now=f[0][i],len=k-2ll*abs(p[i]);
		int lc=upper_bound(p+t,p+n+1,len)-p-1;
		if (lc<t) continue;
		ans=max(ans,now+ck(t,lc));
	}
	for (int i=t;i<=n;i++)
	if (2ll*p[i]<=k)
	{
		long long now=f[0][i],len=k-2ll*p[i];
		int lc=lower_bound(p+1,p+t,-len)-p;
		if (lc>=t) continue;
		ans=max(ans,now+ck(lc,t-1));
	}
	printf("%lld\n",ans);
return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 30ms, 内存消耗: 3296K, 提交时间: 2020-06-17 19:25:58

#include<bits/stdc++.h>
using namespace std;

int A[100005],B[100005],W[100005],Max1[100005]={0},Max2[100005]={0};
int main()
{
    int i,j,n,x,s,a=0,b=0,ans=0;
    scanf("%d%d",&n,&x);
    for(i=1;i<=n;i++)
    {
    	scanf("%d",&j);
    	if(j<0)A[++a]=-j;
    	else B[++b]=j;
	}
	for(i=1;i<=n;i++)scanf("%d",&W[i]);
	for(i=1;i<=a/2;i++)swap(W[i],W[a-i+1]),swap(A[i],A[a-i+1]);
	for(s=0,i=1;i<=a;i++)s+=W[i],Max1[i]=max(s,Max1[i-1]);
	for(s=0,i=1;i<=b;i++)s+=W[a+i],Max2[i]=max(s,Max2[i-1]);
	if(a&&A[1]==1&&b&&B[1]==1)ans=max(W[1],W[1+a]);
	for(s=0,i=1;i<=a&&A[i]<=x;i++)
	{
		j=upper_bound(B+1,B+1+b,x-2*A[i])-B-1;
		s+=W[i],ans=max(ans,s+Max2[j]);
	}
	for(s=0,i=1;i<=b&&B[i]<=x;i++)
	{
		j=upper_bound(A+1,A+1+a,x-2*B[i])-A-1;
		s+=W[a+i],ans=max(ans,s+Max1[j]);
	}
	printf("%d\n",ans);
}

上一题