D. Juego pequeño de srf (pensamiento inverso + juego + optimización de árbol de cola monótona / segmento de línea de dp)

https://blog.csdn.net/zstuyyyyccccbbbb/article/details/112912657 (Adjunte una pregunta similar primero)


Idea: Al observar la muestra, la respuesta a srf y qtc es tomar un signo negativo. Así que considere la puntuación obtenida cuando el srf se mueve por primera vez, el valor máximo de la puntuación qtc.

¿Por qué tomar el signo menos? Por ejemplo:

2 2

1 2

srf es el primero en tomar los 2 mejores, por lo que no será necesario tomar qtc. Entonces la primera respuesta es 2

Qtc primero, la pregunta realmente significa que primero desea considerar la puntuación máxima obtenida por qtc-srf. De manera similar, en este momento, qtc se puede considerar como srf y 2 es el mejor. La puntuación es 2. La pregunta final dice que pase lo que pase, genere la puntuación de srf-qtc, así que tome un número negativo.

Así que aquí simplemente consideramos primero la situación de srf.

En primer lugar, después de que srf toma la posición de i, qtc puede tomar un número de i + 1 a i + m, pero si se desliza, afectará el estado posterior de srf.

Hasta aquí, este tema nos ilumina: si el estado positivo es colisión, entonces regrese. Y es muy probable que sea una transferencia de tipo dp.

Aquí puedes echar un vistazo al problema de la torre baliza de ayer, imitando el diseño. De atrás hacia adelante, dp [i] indica que srf toma el número i. En este momento, [i ~ n] obtiene el valor máximo de srf first-qtc score.

Considere la transferencia: dp [i] = a [i] -max (dp [i + 1 ~ i + m]);

Esta transferencia tiene su propio camino. El diseño de la ecuación de algunos amigos del grupo es diferente, y la transferencia también es diferente. Entonces me desmayé toda la noche e hice este problema de acuerdo con mis propias ideas en la mañana. Si no lo entiende, puede consultar los blogs de otros amigos del 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 transferencia es así. srf toma 1. Debido al juego, es decir, el oponente es un Alpha Dog, encontrará el valor máximo que puede obtener para hacer la respuesta lo más pequeña posible. En [i + 1 ~ i + m], el perro es el primero en moverse, toma el estado máximo, que es el estado del srf que se ha actualizado antes, y elige el más grande para reducir la puntuación. (Juego de azar)

Finalmente, aquí hay un dp que necesita encontrar el mejor valor. No estoy muy familiarizado con las colas monótonas, así que fui al árbol del segmento de línea. (La optimización de la cola monótona puede referirse al clúster anterior)

(La nota es la ecuación ingenua)

#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;
}

 

Supongo que te gusta

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/112981622
Recomendado
Clasificación