Codeforces Gym100342E Minima

Problem E. Minima

Input file: minima.in
Output file: minima.out
Time limit: 2 seconds
Memory limit: 512 megabytes

You are given an array x[1 … n] and a number m. For all i from 1 to n−m+ 1 find the minimum among x[i], x[i + 1], … ,
x[i + m − 1] and return the sum of those minima.

Input

The first line of the input file contains three integer numbers: n, m and k (1 ≤ n ≤ 30 000 000, 1 ≤ m ≤ n,2 ≤ k ≤ min(n,1000)). The second line of the input file contains three integer numbers: a, b and c(−2^31 ≤ a, b, c ≤ 2^31 − 1). The third line of the input file contains k integer numbers: x[1],x[2], … , x[k](−2^31 ≤ x[i] ≤ 2^31 − 1).The rest of the array is calculated using the following formula: x[i] = f(a · x[i − 2] + b · x[i − 1] + c). Heref(y) returns such number −2^31 ≤ z ≤ 2^31 − 1 that y − z is divisible by 2^32.

Output

Print one integer number — the sum of minima of all subarrays of length m of the given array.

Example

minima.in
10 3 2
1 1 0
0 1
minima.out
33
minima.in
1000000 15 5
283471207 23947205 3
17625384 939393931 1838388 912740247 290470294
minima.out
-1879262596173354

题意

一段长为n的序列,给出前k项,后面n-k项可由题目中的函数推算,求所有长为m的区间的最小值之和

题解

维护一个双向队列即可,直接用优先队列会TLE。AC代码如下

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstdlib>

using namespace std;

struct node
{
    int num;
    int id;
    bool operator<(const node &R)const
    {
        return num>R.num;
    }
};
deque<node> Q;
int n,m,k;
int a,b,c;
int f1,f2;
int temp;
node shit;
long long ans=0;
int f(int x)
{
    if(x<k-1)
    {
        scanf("%d",&x);
        return x;
    }
    else if(x==k-1)
    {
        scanf("%d",&f1);
        return f1;
    }
    else if(x==k)
    {
        scanf("%d",&f2);
        return f2;
    }
    else
    {
        int t=a*f1+b*f2+c;
        f1=f2;
        f2=t;
        return t;
    }
}
int main()
{
    freopen("minima.in","r",stdin);
    freopen("minima.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    scanf("%d%d%d",&a,&b,&c);
    int i;
    for(i=1;i<m;i++)
    {
        temp=f(i);
        while((!Q.empty())&&Q.back().num>temp)
            Q.pop_back();
        Q.push_back((node){temp,i});
    }
    for(;i<=n;i++)
    {
        temp=f(i);
        while((!Q.empty())&&Q.back().num>temp)
            Q.pop_back();
        Q.push_back((node){temp,i});
        while(Q.front().id<i-m+1)
            Q.pop_front();
        ans+=Q.front().num;
    }
    printf("%I64d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值