https://blog.csdn.net/zstuyyyyccccbbbb/article/details/112912657 (Anexe uma pergunta semelhante primeiro)
Idéia: Observando a amostra, a resposta para srf e qtc é pegar um sinal negativo. Portanto, considere a pontuação obtida quando o srf se move pela primeira vez - o valor máximo da pontuação qtc.
Por que usar o sinal de menos? Por exemplo:
2 2
1 2
srf é o primeiro a pegar os 2 melhores, então qtc não precisa ser levado. Portanto, a primeira resposta é 2
Qtc primeiro, a questão realmente significa que você deseja considerar a pontuação máxima obtida por qtc-srf primeiro. Da mesma forma, neste momento, considere qtc como srf, e 2 é o melhor. A pontuação é 2. A pergunta final diz que não importa o que aconteça, imprima a pontuação de srf-qtc, então pegue um número negativo.
Portanto, aqui simplesmente consideramos a situação de srf primeiro.
Em primeiro lugar, depois que srf assume a posição de i, qtc pode assumir um número de i + 1 a i + m, mas se estiver passando, afetará o estado subsequente de srf.
Até este ponto, este tópico nos inspirou: se o estado atual é colisão, então volte para trás. E é muito provável que seja uma transferência semelhante a dp.
Aqui você pode dar uma olhada no problema da torre do farol de ontem, imitando o design. De trás para a frente, dp [i] indica que srf leva o número i. Nesse momento, [i ~ n] obtém o valor máximo da pontuação srf first-qtc.
Considere a transferência: dp [i] = a [i] -max (dp [i + 1 ~ i + m]);
Essa transferência tem seu próprio caminho. O desenho da equação de alguns amigos do grupo é diferente, e a transferência também é diferente. Então, desmaiei a noite toda e resolvi esse problema de acordo com minhas próprias idéias pela manhã. Se você não entende, pode consultar os blogs de outros amigos do grupo.
( https://blog.csdn.net/weixin_45948940/article/details/112934074?utm_source=app&app_version=4.5.0
https://blog.csdn.net/tlyzxc/article/details/112976251)
Esta transferência é assim. srf leva 1. Por causa do jogo, ou seja, o oponente é um Alpha Dog, ele encontrará o valor máximo que pode obter para tornar a resposta o menor possível. Em [i + 1 ~ i + m], o cão é o primeiro a se mover. Ele pega o estado máximo, que é o estado do srf que foi atualizado antes, e escolhe o maior para diminuir a pontuação. (Jogos)
Finalmente, aqui está um dp que precisa encontrar o melhor valor. Não estou muito familiarizado com filas monótonas, então fui para a árvore de segmento de linha. (A otimização da fila monotônica pode se referir ao cluster acima)
(A nota é a equação ingênua)
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
LL dp[maxn],a[maxn];
struct Tree{
LL l,r,maxval,tag;///区间最大值
}tree[maxn*4];
void push_up(LL p)
{
tree[p].maxval=max(tree[p*2].maxval,tree[p*2+1].maxval);
}
void addtag(LL p,LL d)
{
tree[p].tag=d;
tree[p].maxval=tree[p].tag;
}
void push_down(LL p)
{
if(tree[p].tag!=-1){
addtag(p*2,tree[p].tag);
addtag(p*2+1,tree[p].tag);
tree[p].tag=-1;
}
}
void build(LL p,LL l,LL r)
{
tree[p].l=l;tree[p].r=r;tree[p].maxval=0;
tree[p].tag=-1;
if(l==r) {tree[p].maxval=0;return;}
LL mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
void modify(LL p,LL l,LL r,LL d)
{
if(l<=tree[p].l&&r>=tree[p].r)///要修改的区间涵盖在区间内部
{
addtag(p,d);
return;
}
push_down(p);
LL mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid) modify(p*2,l,r,d);
if(r>mid) modify(p*2+1,l,r,d);
push_up(p);
}
LL query(LL p,LL l,LL r)
{
if(l<=tree[p].l&&r>=tree[p].r)
{
return tree[p].maxval;
}
LL ans=-1e18;
push_down(p);
LL mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid) ans=max(ans,query(p*2,l,r));
if(r>mid) ans=max(ans,query(p*2+1,l,r));
return ans;
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,m;cin>>n>>m;
build(1,1,n);
for(LL i=1;i<=n;i++) cin>>a[i];
for(LL i=1;i<=max(m,n)+10;i++) dp[i]=-1e18;
dp[n]=a[n];
modify(1,n,n,a[n]);
for(LL i=n-1;i>=1;i--){
LL temp=-1e18;
temp=max(temp,query(1,i+1,min(i+m,n)));
// for(LL j=i+1;j<=min(i+m,n);j++){
// temp=max(dp[j],temp);
// }
dp[i]=a[i]-temp;
modify(1,i,i,dp[i]);
}
LL ans=-0x3f3f3f3f;
for(LL i=1;i<=m;i++){
ans=max(ans,dp[i]);
}
cout<<ans<<endl<<-ans<<endl;
return 0;
}