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;
}

http://acm.hdu.edu.cn/showproblem.php?pid=6047

posted @ 2017-08-06 14:26  达达Mr_X  阅读(254)  评论(0)    收藏  举报