HDU6047---Maximum Sequence(2017多校联赛C题)

来源:互联网 发布:mac版cdr 编辑:程序博客网 时间:2024/06/03 20:17

【题目来源】:http://acm.hdu.edu.cn/showproblem.php?pid=6047
【题意】
给出序列a和序列b,均有n项,让求后n项的最大和。
并且给出了一个关系,是a[x] =max( a[j]-j),(b[k]<=j小于i)
我的理解是:因为b[k]是只能用一次的,所以,就使得a[j]-j这个式子的最大值要多次利用,怎么才能多次利用呢?就要考虑到b[k]对a[j]取值的影响。
比如样例:
8 11 8 5
3 1 4 2
这里,第一步取b数组中的2,所以a[2]…a[4]都可以用,但是当然要取最大值,所以取出11-2,也就是a[5]=9,
第二部取b数组中的1,此时,a[1]..a[5]都可以用,当然,虽然加了a[5],但是a[2]-2依旧是最大,所以使用。
也就是说,要使得最大的值尽可能多次利用,就是解决本题的关键。

//利用优先队列每次挑出最大值,根据他对应的j去处理对应的b[k]#include<map>#include<queue>#include<cmath>#include<vector>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int mod=1e9+7;typedef long long LL;int b[250000+10];int w[250000+10];struct pp{    int index;    int ans;}a[250000+10];struct cmp{    bool operator()(pp s,pp t)    {        if(s.ans==t.ans)            return s.index>t.index;        return s.ans<t.ans;    }};priority_queue<pp,vector<pp>,cmp> q;int main(){    int n;    while(~scanf("%d",&n))    {        while(!q.empty()) q.pop();        for(int i=1;i<=n;i++)        {            a[i].index=i;            scanf("%d",&a[i].ans);            a[i].ans-=i;            q.push(a[i]);        }        for(int i=1;i<=n;i++)            scanf("%d",&b[i]);        memset(w,0,sizeof(w));        for(int i=1;i<=n;i++)            w[b[i]]++;        LL sum=0;        int pos=n;        int d_m=0;        while(1)        {            pp T_T=q.top();            q.pop();            LL num=0;            if(T_T.index<=d_m)  continue;            else            {                for(int i=d_m+1;i<=T_T.index;i++)                    num+=w[i];                d_m=T_T.index;            }            sum+=(num*T_T.ans)%mod;            sum%=mod;            pp x_s;            x_s.index=pos+1;            x_s.ans=T_T.ans-pos-1;            q.push(x_s);            pos+=num;            if(pos==2*n) break;        }        printf("%lld\n",sum);    }}
原创粉丝点击