L捕鱼达人-题解

2020年“远光杯”粤澳计算机程序设计大赛网络资格赛

下面是题目和代码。

门前大桥下,游过一群鱼,小红鱼,黄花鱼,绿草鱼,蓝顶鱼,粉鲳鱼,砂紫鱼,竟然在鱼塘中排成了一条队列,捕鱼达人坤坤打算将他们捕获。但是由于这些鱼比较稀有,坤坤需要在指定的规则下才能抓捕他们,规则如下:

1. 在捕鱼过程中当前捕获的鱼颜值必须大于等于前一条鱼颜值a_i,对于捕获的第一条鱼没有要求。

2. 每一条鱼变身后他的价值b_i为他的颜值的1/10000(整除)。

3. 每一条鱼变身后他的颜值会变成原本颜值对10000的余数,也就是a_i%10000。(例如变身前颜值a_i为20001,则变身后它的价值变为2,颜值变为1)。

4. 所有鱼在一开始的时候就会变身,变身后坤坤才可以开始捕鱼。

5. 鱼群顺序是从左到右排列的,鱼群的顺序是不可变的,坤坤可以从鱼群头或者鱼群尾开始捕鱼,但是顺序必须是从左到右或者从右到左。

6. 坤坤希望他捕获到的鱼的价值最多。

输入要求
第一行先输入一个T(1 <= T <= 10)表示接下去有T组数据

对于每组数据

第一行会有一个n(1 <= n <= 10^4)表示接下来从左到右会有n条鱼。

第二行会有n个数,对于每个数表示这个鱼的颜值为a_i(-6 * 10^4 < a_i < 6 * 10^4)。

输出要求
对于每组数据,输出Case #i: val

表示当前为第i组数据,每次捕鱼获得的最大价值为val。

对于每行输出,最后没有空格,输出后直接换行。

输入
5  
5  
10001 10002 10003 10004 10001  
5  
50001 10001 10002 10003 10004  
5  
50001 10002 10003 10004 10005  
5  
50005 10001 10002 10003 10004  
5  
-10001 -10002 -10003 -10004 0  

输出
Case #1: 4
Case #2: 9
Case #3: 9
Case #4: 6
Case #5: 0
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 20010
#define M 10010
#define INF 1e-9
typedef struct node{
	int l,r,v;
}Node;
Node a[4*N];
const int mod=10000;
int apr[M],val[M],dp[M];
void build(int le,int ri,int no){
	if(le==ri)
	{
		a[no].l=le,a[no].r=ri;
		a[no].v=0;
		return ;
	}
	int mid=(le+ri)/2;
	build(le,mid,no<<1);
	build(mid+1,ri,no<<1 | 1);
	a[no].l=le,a[no].r=ri;
	a[no].v=max(a[no<<1].v,a[no<<1 | 1].v);
}
int query(int le,int ri,int no){
	if(a[no].l==le&&a[no].r==ri)
	{
		return a[no].v;
	}
	int mid=(a[no].l+a[no].r)/2;
	int ans=-mod;
	if(ri<=mid)
	{
		ans=max(ans,query(le,ri,no<<1));
		
	}
	else if(le>mid)
	{
		ans=max(ans,query(le,ri,no<<1|1));	
	}
	else 
	{
		ans=max(ans,query(le,mid,no<<1));
		ans=max(ans,query(mid+1,ri,no<<1|1));
	}
	return ans; 
}
void update(int le,int ri,int no,int val){
	if(a[no].l==a[no].r&&a[no].r==ri)
	{
		a[no].v=max(a[no].v,val);
		return ;
	}
	int mid=(a[no].l+a[no].r)/2;
	if(ri<=mid)
	{
		update(le,ri,no<<1,val);
	}
	else
	{
		update(mid+1,ri,no<<1|1,val);
	}
	a[no].v=max(a[no<<1].v,a[no<<1|1].v);
}
int main(){
	int t,n,ans,cnt=1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		int bor=-mod;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&apr[i]);
			val[i]=apr[i]/mod;
			apr[i]=apr[i]%mod+mod;
			bor=max(bor,apr[i]);
		}
		int ans=INF,mx;
		build(1,bor,1);
		for(int i=0;i<n;i++)
		{
			mx=query(1,apr[i],1);
			dp[i]=mx+val[i];
			ans=max(ans,dp[i]);
			update(1,apr[i],1,dp[i]);
		}
		build(1,bor,1);
		for(int i=n-1;i>=0;i--)
		{
			mx=query(1,apr[i],1);
			dp[i]=mx+val[i];
			ans=max(ans,dp[i]);
			update(1,apr[i],1,dp[i]);
		}
		printf("Case #%d: %d\n",cnt,ans);
		cnt++;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值