E. Greedy Shopping (pensamento + intervalo de manutenção da árvore de segmento de linha é o melhor valor)

https://codeforces.com/contest/1440/problem/E

Pergunta: Existem n lojas, comprar itens na i-ésima loja custa a [i] yuans. A sequência a é garantida como não crescente

Duas operações:
① 1 xy defina a [i] no intervalo [1, x] para a [i] = max (a [i], y);
② 2 xy você tem y yuan, começando do número x Começando pela loja, percorra todas as lojas por vez até chegar à loja n, se você pode comprar os itens na loja atual, compre. Pergunte quantos itens você pode comprar


Idéia: Na verdade, a árvore de segmento de linha mais óbvia requer um pouco de reflexão. Comece a cortar na árvore de segmento de linha. Tudo bem, mas é mais problemático.

A primeira observação é uma sequência não crescente. Portanto, de acordo com a operação 1, se o valor máximo do intervalo atualmente coberto <= y, então modifique-o, e se o valor mínimo do intervalo atualmente coberto> y, então ele não será modificado. (Manter o valor mínimo é para poda, caso contrário, TLE5) Em seguida, vá para lazytag.

Para a operação dois, consulta de intervalo, se o valor mínimo do intervalo atual> x, significa que o intervalo não precisa ser adquirido. Caso contrário, repita primeiro a subárvore esquerda e, em seguida, repasse a subárvore direita. Se houver um intervalo de intervalos e <= dinheiro próprio, compre-o. Caso contrário, você não pode comprar e continuar recursivamente. Economize dinheiro na referência de função ao mantê-la.

A ideia não é clara ao escrever e a compreensão da árvore do segmento de linha precisa ser fortalecida.

Recomenda-se que, quando a consulta de intervalo for modificada, o julgamento if julgue apenas se a cobertura do intervalo foi satisfeita e, então, várias condições sejam julgadas nele. Preste atenção ao nó folha neste momento, e é necessário calcular se ele pode ser comprado e preste atenção ao limite recursivo.

#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=2e5+100;
typedef long long LL;
LL a[maxn];
struct Tree{
    LL l,r,maxval,minval,sum,tag;///区间最大值,区间最小值,区间和,l
}tree[maxn*4];
void push_up(LL p)
{
    tree[p].maxval=max(tree[p*2].maxval,tree[p*2+1].maxval);
    tree[p].minval=min(tree[p*2].minval,tree[p*2+1].minval);
    tree[p].sum=tree[p*2].sum+tree[p*2+1].sum;
}
void addtag(LL p,LL d)
{
    tree[p].tag=d;
    tree[p].sum=tree[p].tag*(tree[p].r-tree[p].l+1);
    tree[p].maxval=tree[p].tag;
    tree[p].minval=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=-1e18;tree[p].minval=1e18;
    tree[p].sum=0;tree[p].tag=-1;
    if(l==r) {tree[p].maxval=tree[p].minval=tree[p].sum=a[l];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)///要修改的区间涵盖在区间内部
    {
        if(tree[p].minval>=d) return;///不剪枝会TLE5
        if(tree[p].maxval<d)
        {
            addtag(p,d);        return;
        }
        if(tree[p].l==tree[p].r) 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,LL &x)
{
    if(l<=tree[p].l&&r>=tree[p].r)
    {
        if(tree[p].minval>x) return 0;
        if(x>=tree[p].sum){
            x-=tree[p].sum;
            return tree[p].r-tree[p].l+1;
        }
        if(tree[p].l==tree[p].r) return 0;///返回到叶子节点的边界,注意叶子节点要考虑付钱
    }
    LL ans=0;
    push_down(p);
    LL mid=(tree[p].l+tree[p].r)>>1;
    if(l<=mid) ans+=query(p*2,l,r,x);
    if(r>mid) ans+=query(p*2+1,l,r,x);
    return ans;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n,m;cin>>n>>m;
  for(LL i=1;i<=n;i++) cin>>a[i];
  build(1,1,n);
  while(m--)
  {
      LL op,l,r;cin>>op>>l>>r;
      if(op==1){
        modify(1,1,l,r);
      }
      else if(op==2){
        cout<<query(1,l,n,r)<<endl;
      }
  }
return 0;
}

 

Acho que você gosta

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