Codeforces Gym 100513F F. Ilya Muromets 线段树

本文解析CodeForces上的一道题目F.IlyaMuromets,通过线段树算法解决双次切割最大火龙威力的问题。介绍了题目背景、算法思路及实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

F. Ilya Muromets

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://codeforces.com/gym/100513/problem/F

Description

I

Ilya Muromets is a legendary bogatyr. Right now he is struggling against Zmej Gorynych, a dragon with n heads numbered from 1 to nfrom left to right.

Making one sweep of sword Ilya Muromets can cut at most k contiguous heads of Zmej Gorynych. Thereafter heads collapse getting rid of empty space between heads. So in a moment before the second sweep all the heads form a contiguous sequence again.

As we all know, dragons can breathe fire. And so does Zmej Gorynych. Each his head has a firepower. The firepower of the i-th head isfi.

Ilya Muromets has time for at most two sword sweeps. The bogatyr wants to reduce dragon's firepower as much as possible. What is the maximum total firepower of heads which Ilya can cut with at most two sword sweeps?

Input

The first line contains a pair of integer numbers n and k (1 ≤ n, k ≤ 2·105) — the number of Gorynych's heads and the maximum number of heads Ilya can cut with a single sword sweep. The second line contains the sequence of integer numbers f1, f2, ..., fn(1 ≤ fi ≤ 2000), where fi is the firepower of the i-th head.

Output

Print the required maximum total head firepower that Ilya can cut.

Sample Input

8 2
1 3 3 1 2 3 11 1

Sample Output

20

HINT

 

题意

一个人可以砍两刀,每刀可以消去连续的K个数,然后问你两刀最多能砍下数的和是多少

题解

线段树,枚举这一块,然后除了这一块的其他块都是可以选择的

查询区间最大值就好了

代码

 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)
const int maxn=2025001;
#define mod 1000000007
#define eps 1e-9
const int inf=0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fLL;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//**************************************************************************************
struct node
{
    int l,r,ma,mi;
}a[maxn];
int d[maxn];
void build(int x,int l,int r)
{
    a[x].l=l,a[x].r=r;
    a[x].ma=-inf,a[x].mi=inf;
    if(l==r)
    {
        a[x].ma=d[l];
        a[x].mi=d[l];
        return;
    }
    else
    {
        int mid=(l+r)>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        a[x].ma=max(a[x<<1].ma,a[x<<1|1].ma);
        a[x].mi=min(a[x<<1].mi,a[x<<1|1].mi);
    }
}
int query1(int x,int st,int ed)
{
    int l=a[x].l,r=a[x].r;
    if(st<=l&&r<=ed)
        return a[x].mi;
    else
    {
        int mid=(l+r)>>1;
        int mi1=inf,mi2=inf;
        if(st<=mid)
            mi1=query1(x<<1,st,ed);
        if(ed>mid)
            mi2=query1(x<<1|1,st,ed);
        return min(mi1,mi2);
    }
}

int query2(int x,int st,int ed)
{
    int l=a[x].l,r=a[x].r;
    if(st<=l&&r<=ed)
        return a[x].ma;
    else
    {
        int mid=(l+r)>>1;
        int mi1=-inf,mi2=-inf;
        if(st<=mid)
            mi1=query2(x<<1,st,ed);
        if(ed>mid)
            mi2=query2(x<<1|1,st,ed);
        return max(mi1,mi2);
    }
}
int aa[maxn];
int dp[maxn];
int sum=0;
int main()
{
    int n=read(),k=read();
    for(int i=1;i<=n;i++)
        aa[i]=read();
    for(int i=1;i<=n;i++)
        sum=sum+aa[i];
    for(int i=1;i<=k;i++)
        dp[i]+=aa[i]+dp[i-1];
    for(int i=k+1;i<=n;i++)
        dp[i]=dp[i-1]+aa[i]-aa[i-k];
    if(2*k>=n)
    {
        cout<<sum<<endl;
        return 0;
    }
    int ans=0;
    for(int i=1;i<=n-k+1;i++)
        d[i]=dp[k-1+i];
    build(1,1,n-k+1);
    for(int i=1;i<=n-k+1;i++)
    {
        if(i>k)
        {
            ans=max(ans,d[i]+query2(1,1,i-k));
        }
        else
            ans=max(ans,d[i]);
    }
    cout<<ans<<endl;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值