zoukankan      html  css  js  c++  java
  • #4306. 贪玩蓝月

    题目描述

    《贪玩蓝月》是目前最火爆的网页游戏。在游戏中每个角色都有若干装备,每件装备有一个特征值 $w$ 和一个战斗力 $v$ 。在每种特定的情况下,你都要选出特征值的和对 $p$ 取模后在一段范围内的装备,而角色死亡时自己的装备会爆掉。每个角色的物品槽可以看成一个双端队列,得到的装备会被放在两端,自己的装备爆掉也会在两端被爆。

    现在我们有若干种事件和询问,如下所示:

    - `IF w v`:在前端加入一件特征值为 $w$ 战斗力为 $v$ 的装备
    - `IG w v`:在后端加入一件特征值为 $w$ 战斗力为 $v$ 的装备
    - `DF`:删除最前端的装备
    - `DG`:删除最后端的装备
    - `QU l r`:在当前的装备中选取若干装备,他们的和对 $p$ 取模后在 $[l, r]$ 中,使得这些装备的战斗力之和最大

    为了锻炼你的水平,请尽量使用在线做法。

    题解

    考虑只加不删的话,那就是普通的 $ ext{dp}$ ,即 $f[i][j]$ 表示前 $i$ 个物品,特征值的和模 $p$ 为 $j$ 的最大战斗力和,然后背包转移即可

    考虑有删数的话,就上线段树分治即可,于是就又是只有加数的了,效率: $O(mplogm)$

    好像有种在线的做法but我不会

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=2e5+5;
    int m,P,b[N],U[N],V[N],G[N];
    LL f[30][500],F[500];
    struct O{int x,y;}a[N];
    vector<O>g[N];char ch[9];
    #define Ls k<<1
    #define Rs k<<1|1
    #define mid ((l+r)>>1)
    void upd(int k,int l,int r,int L,int R,O v){
        if (L<=l && r<=R){
            g[k].push_back(v);return;
        }
        if (mid>=L) upd(Ls,l,mid,L,R,v);
        if (mid<R) upd(Rs,mid+1,r,L,R,v);
    }
    void qry(int k,int l,int r,int d){
        int z=g[k].size();
        for (int x,y,i=0;i<z;i++){
            x=g[k][i].x,y=g[k][i].y;
            for (int j=0;j<P;j++)
                F[(j+x)%P]=f[d][j]+y;
            for (int j=0;j<P;j++)
                f[d][j]=max(f[d][j],F[j]);
        }
        if (l==r){
            if (G[l]){
                LL v=-1;
                for (int i=U[l];i<=V[l];i++)
                    v=max(v,f[d][i]);
                printf("%lld
    ",v);
            }
            return;
        }
        else{
            for (int i=0;i<P;i++)
                f[d+1][i]=f[d][i];
            qry(Ls,l,mid,d+1);
            for (int i=0;i<P;i++)
                f[d+1][i]=f[d][i];
            qry(Rs,mid+1,r,d+1);
        }
    }
    int main(){
        cin>>m;cin>>m>>P;
        int l=m+1,r=m;
        for (int i=1;i<=m;i++){
            scanf("%s",ch);
            if (ch[0]=='I'){
                if (ch[1]=='F') b[--l]=i,
                    scanf("%d%d",&a[l].x,&a[l].y);
                else b[++r]=i,
                    scanf("%d%d",&a[r].x,&a[r].y);
            }
            else if (ch[0]=='Q')
                G[i]=1,scanf("%d%d",&U[i],&V[i]);
            else{
                if (ch[1]=='F') upd(1,1,m,b[l],i,a[l]),l++;
                else upd(1,1,m,b[r],i,a[r]),r--;
            }
        }
        for (int i=l;i<=r;i++) upd(1,1,m,b[i],m,a[i]);
        for (int i=1;i<P;i++) f[0][i]=-2e18;
        qry(1,1,m,0);return 0;
    }
  • 相关阅读:
    财务系统重复付款case分析及解决方案
    MySQL体系结构
    安装篇九:安装wordpress(5.4版本)
    安装篇八:配置 Nginx 使其支持 MySQL 应用
    安装篇七:配置 Nginx 使其支持 PHP 应用
    安装篇六:安装PHP(7.2.29版本)
    安装篇五:安装MySQL(5.6.38版本)
    安装篇四:安装NGINX(1.4.0版本)
    安装篇三:系统初始化设置
    安装篇二:CentOS 6.9系统安装
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12309679.html
Copyright © 2011-2022 走看看