HDU 6047 Maximum Sequence(贪心)

来源:互联网 发布:jq 数组包含 编辑:程序博客网 时间:2024/06/17 23:58

Description
给出两个长度为n的序列a和b,要求用b序列构造a序列的第n+1~2n项,在构造a[i] (n+1<=i<=2n) 时每次需要从b序列中选一个数b[k](一个数只能被选一次),a[i]需要满足a[i]<=max{ a[j]-j | b[k]<=j < i },问构造出来的a[n+1]+…+a[2n]的最大值
Input
多组用例,每组用例输入一整数n表示序列长度,之后输入两个长度为n的序列a和b,以文件尾结束输入(1<=n<=250000,n<=a[i]<=1500000,1<=b[i]<=n)
Output
输出a[n+1]+…+a[2n]的最大值,结果模1e9+7
Sample Input
4
8 11 8 5
3 1 4 2
Sample Output
27
Solution
注意到如果a[i]满足的条件是a[i]<=max{ a[j]-j | b[k]<=j<=n }的话那么答案是固定的,而变成a[i]<=max{ a[j]-j | b[k]<=j < i }后,每次a[i]的取值还取决于a[n+1]~a[i-1],所以想让和最大,那么之前的a[i]要尽可能大,也就是说每次a[i]要取最大范围的最大值,进而每次取最小的b[k]即可,维护a[i]-i序列的后缀最大值M[i]和a[i]-i(i>=n+1)的最大值Max,第i次取出第i小的b[i],a[n+i]即为max(M[b[i]],Max)
Code

#include<cstdio>#include<algorithm>using namespace std;const int maxn=250001,mod=1e9+7;int n,a[maxn],b[maxn],m[maxn];int main(){    while(~scanf("%d",&n))    {        for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]-=i;        for(int i=1;i<=n;i++)scanf("%d",&b[i]);        sort(b+1,b+n+1);        m[n]=a[n];        for(int i=n-1;i>=1;i--)m[i]=m[i+1]>a[i]?m[i+1]:a[i];        int ans=0,t,Max=0;        for(int i=1;i<=n;i++)        {            t=max(m[b[i]],Max);            Max=max(Max,t-i-n);            ans+=t;            if(ans>=mod)ans-=mod;        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击