hdu6047 Maximum Sequence

来源:互联网 发布:数控车床编程100例 编辑:程序博客网 时间:2024/06/05 06:24

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6047


题意:

给你n个a,a[1]~a[n],和n个b,b[1]~b[n],现在让你补全接下来n个a(从a[n+1]~a[2n),规则是:选一个b[i],在a[b[i]]~a[n]这段区间中能够取得一个a[j]-j(满足a[j]-j 在这段区间中值最大),补全到a[n+1]~a[2n]里。最后让你输出a[n+1]~a[2n]的和,且要保证此和最大,结果 mod 1e9+7;


解:

一开始想的很复杂,因为又要考虑到b也得考虑到a, 没什么思路,后来看了一位博主的博客,虽然没看懂,但却受到了启发。

首先我们知道,在a[1]~a[n]中,无论怎么取,都会是较小的取最大的,那我们不妨来拿样例说事。

8   11   8    5

9    9    5    1

在8的位置应该是7,因为后面的9较大,那么在对应区间应该取9

那么,我们会发现其实b[i],的取法顺序是没必要考虑的,每次从头开始取,因为肯定前面的数大(较小的被后面较大的覆盖),

那么在n+1位置新添加的数最大,之后添加的数只用考虑a[j]-j是不是比a[n+1]大就行。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#define Mem(a,b) memset(a,b,sizeof(a));using namespace std;typedef long long ll;const int maxn=5e5+50;const int x=1e9+7;int a[maxn],b[maxn];int mxx[maxn];int main(){    int n;    while(~scanf("%d",&n))    {        Mem(mxx,0);        for(int i=1;i<=n;i++)        scanf("%d",&a[i]);        for(int i=1;i<=n;i++)        scanf("%d",&b[i]);        mxx[n]=a[n]-n;        for(int i=n-1;i>=1;i--)        {            mxx[i]=max(mxx[i+1],a[i]-i);        }        sort(b+1,b+n+1);        ll ans=0;        int tmp=mxx[b[1]]-(n+1);        ans+=(ll)mxx[b[1]];        for(int i=2;i<=n;i++)        {            int p=mxx[b[i]];            int m=max(p,tmp);            ans+=(ll)m;        }        ans%=x;        printf("%lld\n",ans);    }    return 0;}


原创粉丝点击