HDU 6047 Maximum Sequence (贪心)
Description
给出两个长度为\(n\)的序列\(a\)和\(b\),要求用\(b\)序列构造\(a\)序列的第\(n+1\)到第\(2n\)项,在构造\(a[i] (n+1 \leqslant i \leqslant 2n)\)时每次需要从\(b\)序列中选一个数\(b[k]\)(一个数只能被选一次),\(a[i]\)需要满足\(a[i] \leqslant max\{ a[j]-j | b[k] \leqslant j < i \}\),问构造出来的\(a[n+1]+ \dots +a[2n]\)的最大值。
Input
多组用例,每组用例输入一整数\(n\)表示序列长度,之后输入两个长度为\(n\)的序列\(a\)和\(b\),以文件尾结束输入。\(1 \leqslant n \leqslant 250000,n \leqslant a[i] \leqslant 1500000,1 \leqslant b[i] \leqslant n\)。
Output
输出\(a[n+1]+ \dots +a[2n]\)的最大值,结果模\(1e9+7\)。
Sample Input
4
8 11 8 5
3 1 4 2
Sample Output
27
Solution
注意到如果\(a[i]\)满足的条件是\(a[i] \leqslant max\{ a[j]-j | b[k] \leqslant j \leqslant n \}\)的话那么答案是固定的,而变成\(a[i] \leqslant max{ a[j]-j | b[k] \leqslant j < i }\)后,每次\(a[i]\)的取值还取决于\(a[n+1]\)到\(a[i-1]\),所以想让和最大,那么之前的\(a[i]\)要尽可能大,也就是说每次\(a[i]\)要取最大范围的最大值,进而每次取最小的\(b[k]\)即可,维护\(a[i]-i\)序列的后缀最大值\(mx[i]\)和\(a[i]-i\ (i \geqslant n+1)\)的最大值\(maxx\),第\(i\)次取出第\(i\)小的\(b[i]\),\(a[n+i]\)即为\(max\{mx[b[i]],maxx\}\)。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 10;
const int N = 3e5 + 10;
int a[N], b[N], mx[N];
int main()
{
int n;
while (~scanf("%d", &n))
{
for (int i = 1; i \leqslant n; i++) scanf("%d", a + i), a[i] -= i;
for (int i = 1; i \leqslant n; i++) scanf("%d", b + i);
sort(b + 1, b + n + 1);
mx[n] = a[n];
for (int i = n - 1; i >= 1; i--) mx[i] = max(mx[i + 1], a[i]);
int ans = 0, maxx = 0;
for (int i = 1; i \leqslant n; i++)
{
int t = max(mx[b[i]], maxx);
ans = (ans + t) % mod;
maxx = max(maxx, t - i - n);
}
printf("%d\n", ans);
}
return 0;
}

浙公网安备 33010602011771号