Given two integer sequences {ai} and {bi} with the same length n, you are to find the next n numbers of {ai}:a
Now Steph finds it too hard to solve the problem, please help him.
For each test case, the first line consists of one integer n. The next line consists of n integers representing {ai}. And the third line consists of n integers representing {bi}.
1≤n≤250000, n≤a_i≤1500000, 1≤b_i≤n.
2. Choose 1 from {bi}, then a_1…a_5 are available for a_6, and you can let a_6=a_2-2=9;
题目大意:
给你一个长度为n的序列a{i}和一个长度为n的序列b{i},要求构建一个新的序列an+1-a2n,并且使得sum=(an+1)+(an+2)+....+(a2n-1)+(a2n)的和最大; 用于构建新的序列的ai是有一定限制条件的:从b序列里面选一个数bk, ai≤max{aj-j│bk≤j<i};
解题思路:
要想使得构建出来的新的序列的所有项之和最大的话 ai=max{aj-j│bk≤j<i},因为只有每一个ai都取最大值时,才会使得所有项之和最大; ai 的选择范围是从bk到a序列的结束,所以只有当bk越小的时候,ai能选择的范围才越大,这样更有可能取到最大的值,先给b序列从小到大排序,v[i]存a[j]-j的值;然后更新v[i]数组,从i=n开始,v[i]=max(v[i],v[i+1]); 这样更新的目的在于,把一个数前面小于它的数,全部更新为本身,也就是更新为一个大的数; 举个例子:比如一开始的时候v[i]数组为:6 7 9 4 5 4 1 ,经过更新之后每个数前面比它小的数就会变成它本身,数组变成:9 9 9 5 5 4 1;
当我们从bk开始到a序列的结束,找一个最大的数的时候,是从前往后找的,也就是说,如果第一个数就正好是bk到a序列的结束中) 最大的数时,那很容易,但是如果不是的话就还要往后找,所以就干脆直接把大数前面小于它的数全都更新为大数,找的时候会大大减少时间复杂度; 更新了a[i]之后,同时更新a[j]-j;每次a[i]的取值就应该是a[i]=max( a[b[i]],maxx),同时maxx=max(maxx,a[b[i]-i-n)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
long long a[250100],b[250100],v[250100];
int n;
int main()
{
while(~scanf("%d",&n))
{
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
v[i]=a[i]-i;
}
for(int i=1;i<=n;i++)
scanf("%lld",&b[i]);
sort(b+1,b+n+1);
for(int i=n;i>=1;i--)
v[i]=max(v[i],v[i+1]);
long long ans=0,maxx=0;
for(int i=1;i<=n;i++)
{
v[b[i]]=max(maxx, v[b[i]]);
ans=(ans+v[b[i]])%mod;
maxx=max(maxx,v[b[i]]-i-n);
}
printf("%lld\n",ans);
}
}
416

被折叠的 条评论
为什么被折叠?



