题目意思就是刚给你两个序列a,b,每次从b中取一个数字到当前ai-i的最后一位最大值赋给a的下一位,那么题目就先把B从小到大排序一下,对a的话预处理一下减去他的下标,从小到大取b,定义一个ans数组,表示从后往前当前位最大值。如{4, 1, 3, 2}, ans则为{4, 3, 3, 2};
对b从左到右查找,每次把ans【i】赋值给ans【i+n】就好了,更新ans数组的话,更新ans【n】就行,O(n)复杂度。
//上来啪嗒啪嗒一个线段树,居然TLE了。。。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define SC(a) scanf("%d",&a)
#define maxn 250021
#define mod 1000000007
typedef long long LL;
int n,arr[maxn],brr[maxn];
int ans[maxn];
int main()
{
while(~SC(n))
{
for(int i=0;i<maxn;i++)
ans[i]=-10000000;
for(int i=1;i<=n;i++) SC(arr[i]);
for(int j=1;j<=n;j++) SC(brr[j]);
for(int i=n;i>0;i--)
{
arr[i]-=i;
ans[i]=max(ans[i+1],arr[i]);
}
// for(int i=1;i<=4;i++)
// cout<<ans[i]<<endl;
sort(brr,brr+n);
LL res=0;
for(int i=1;i<=n;i++)
{
res+=max(ans[brr[i]],ans[n]);
res%=mod;
ans[n]=max(ans[n],ans[brr[i]]-i-n);
}
printf("%lld\n",res);
}
}