17暑假多校联赛2.3 HDU 6047 Maximum Sequence

来源:互联网 发布:手机giftbox是什么软件 编辑:程序博客网 时间:2024/05/26 15:56

Maximum Sequence

Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)

Problem Description

Steph is extremely obsessed with “sequence problems” that are usually seen on magazines: Given the sequence 11, 23, 30, 35, what is the next number? Steph always finds them too easy for such a genius like himself until one day Klay comes up with a problem and ask him about it.

Given two integer sequences {ai} and {bi} with the same length n, you are to find the next n numbers of {ai}: an+1…a2n. Just like always, there are some restrictions on an+1…a2n: for each number ai, you must choose a number bk from {bi}, and it must satisfy ai≤max{aj-j│bk≤j

Input

The input contains no more than 20 test cases.
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.

Output

For each test case, print the answer on one line: max{∑2nn+1ai} modulo 109+7。

Sample Input

48 11 8 53 1 4 2

Sample Output

27
HintFor the first sample:1. Choose 2 from {bi}, then a_2a_4 are available for a_5, and you can let a_5=a_2-2=9; 2. Choose 1 from {bi}, then a_1a_5 are available for a_6, and you can let a_6=a_2-2=9;


题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047

分析

题意:给出两个长度为n的数组a,b,下标为1到n,给定a[n]到a[2n]满足的关系式 a[i]≤max{a[j]-j│b[k] ≤ j < i},现在要计算a[n]到a[2n]的总和的最大值,其中b中的元素每个只能用一次
由关系式可以知道a[i]{ i | n < i ≤ 2n }的值为a[b[k]]-b[k]到a[i-1]-(i-1)的最大值,所以b的值直接按照从小到大的顺序使用就可以了,可以用线段树来做,也可以直接循环嵌套来做

代码

#include <iostream>#include <stdio.h>#include <math.h>#include <string.h>#include <algorithm>#define MAXN 500050#define ll long longusing namespace std;const int MOD=1e9+7;int main(){    int n;    ll d[MAXN];///存放a[b[k]]到a[i-1]的最大值    while(~scanf("%d",&n))    {        ll a[MAXN];        int c,b[MAXN];        memset(d,0,sizeof(d));        a[0]=0;        b[0]=0;        for(int i=1; i<=n; i++)        {            scanf("%d",&c);            a[i]=c-i;///直接存放a[i]-i的值        }        for(int i=1; i<=n; i++)        {            scanf("%d",&b[i]);        }        sort(b+1,b+n+1);///将b排序,下标从1开始到n        int y=n,k=1,i=0,pos;        ll sum=0;///由于结果可能非常大,所以用long long,否则会WA掉        while(y<2*n)///当y>=2*n时,说明已经a[n]到a[2n]的值已全部算出        {            if(i>n&&a[i]<d[b[k-1]]&&b[k]<=pos)            ///如果循环不是第一次,则a中已经插入了新的值,需要比较新的值与之前的最大值的大小            ///如果之前的最大值的位置pos在新的b[k]之后,则最大值可以不变,直接赋给新的d[b[k]]            ///用这个判断可以减少好多次后面的循环,节省好多时间,否则会时间超限                d[b[k]]=d[b[k-1]];            else for(i=b[k]; i<=y; i++)///循环来得到a[b[k]]到a[i]的最大值            {                d[b[k]]=max(d[b[k]],a[i]);                if(d[b[k]]==a[i])pos=i;///记录最大值的下标            }            i=y+1;            a[i]=d[b[k]]-i;///将得到的值减去它的下标存到a数组中            sum=(sum+d[b[k]])%MOD;///将得到的a[i]的值加入总和,并每次都取余            k++;///b[k]的值只能使用一次,所以k++            y++;///将需要取最大值的区间的右边界加1,来将新加入的值包含到区间内        }        printf("%lld\n",sum);    }}
阅读全文
1 0