HDU6047 Maximum Sequence(贪心,2017 HDU多校联赛 第2场)

题目;
Maximum Sequence

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 57 Accepted Submission(s): 25

Problem Description
Steph is extremely obsessed with “sequence problems” that are usually seen on magazines: Given the sequence 11, 23, 30, 35, what is the next number? Steph always finds them too easy for such a genius like himself until one day Klay comes up with a problem and ask him about it.

Given two integer sequences {ai} and {bi} with the same length n, you are to find the next n numbers of {ai}: an+1…a2n. Just like always, there are some restrictions on an+1…a2n: for each number ai, you must choose a number bk from {bi}, and it must satisfy ai≤max{aj-j│bk≤j

思路:

题意是给了一个a数组,长度是n,然后要求从a[n+1]~a[2*n]的和

它的计算方法是这样的;
从a[n+1]开始,a[j]的值等于你在b数组中选一个数字k,那么a[j]的值就是a[j]-j(j<k<i)的最大值

以第一个样例来说明

编号1234
a81185
b3142

我们第一次从b数组选出来的数字是2,那么
从a[2]开始算起
a[2]-2=9
a[3]-3=5
a[4]-4=1
a[5]的值就是他们中间最大的,也就是a[5]=9

到了计算a[6]的情况,这次我们在b数组里面选择1
a[1]-1=7
a[2]-2=9
a[3]-3=5
a[4]-4=1
a[5]-5=4

所以a[6]的值是9,以此类推
a[7]=5,a[8]=4

他们的和=9+9+5+4=27

我们的做法是直接在a[i]中存储a[i]-i的值,然后定义数组ma[i],代表以i为起点,到后面区间所能得到最大值

然后后开一个优先队列,让值比较大的先出队,把b数组中的每一个ma[b[i]]值都放到优先队列中,每次取队首,那么队首就是我们所要求的那个最大值,用tmp来存储n+1以后a[i]-i的最大值,每次更新a[i],最后取模就是答案,具体看代码

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define N 250010
#define ll long long
using namespace std;
const int mod=1e9+7;
int a[N*2],b[N],ma[N];
int main()
{
  int n;
  while(~scanf("%d",&n))
  {
      mem(ma,0);mem(a,0);
      int x;
      for(int i=1; i<=n; i++)
      {
          scanf("%d",&x);
          a[i]=x-i;
      }
      for(int i=n; i>=1; i--)
          ma[i]=max(a[i],ma[i+1]);//计算从i为开始,所能达到的最大值
      for(int i=1; i<=n; i++)
          scanf("%d",&b[i]);
      priority_queue<int>q;
      for(int i=1; i<=n; i++)
          q.push(ma[b[i]]);
      int ans=0,tmp=0;
      for(int i=n+1; i<=2*n; i++)
      {
          int s=q.top();
          if(tmp>s)
              a[i]=tmp-i;
          else
          {
              a[i]=s-i;
              q.pop();
          }
          ans=(ans+a[i]+i)%mod;
          tmp=max(tmp,a[i]);
      }
      printf("%d\n",ans%mod);
  }
  return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值