无聊开始水题

退役已久假期无聊水了水题。

正解是前后缀单队背包n^2预处理mq询问,

用消失之物+单队水过了,n^2log预处理,o(q)询问;(毕竟和原题挺像的,第一个想到的就是这个)

#include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define LL long long
#define pf(a) printf("%d ",a)
#define phn puts("")
using namespace std;
int read();
/* 扫左走右,扫右走左。seg+单队背包 
从0编号,询问编号加1*/
int n;
const int N =1110;
int a[N],b[N],c[N];
int ans[N][N],f[N],g[2][N],que[N],hd,tl;
void cal(int &p,int i){
    p=!p;
    for(int j=0;j<a[i];++j){
        hd=1;que[tl=1]=j;g[p][j]=g[!p][j];
        for(int k=j+a[i];k<=1000;k+=a[i]){
            g[p][k]=max(g[!p][que[hd]]+(k-que[hd])/a[i]*b[i],g[!p][k]);
            while(hd<=tl&&que[hd]+c[i]*a[i]<k+a[i])++hd;
            while(hd<=tl&&g[!p][que[tl]]+(k-que[tl])/a[i]*b[i]<g[!p][k])--tl;
            que[++tl]=k;
        }
    }
}
void dp(int l,int r){
    if(l==r){memcpy(ans[l],f,sizeof(f));return;}
    int z=l+r>>1;
    int sto[N]={0};
    //memset sto
    memcpy(sto,f,sizeof(f));
    //memset(g[1],0,sizeof(g[1]));
    int p=0;
    memcpy(g[0],f,sizeof(f));
    F(i,z+1,r)cal(p,i);
    memcpy(f,g[p],sizeof(f));
    dp(l,z);
    p=0;
    memcpy(g[0],sto,sizeof(sto));
    F(i,l,z)cal(p,i);
    memcpy(f,g[p],sizeof(f));
    dp(z+1,r);
    memcpy(f,sto,sizeof(f));
}
int main(){
    n=read();
    F(i,1,n)a[i]=read(),b[i]=read(),c[i]=read();
    dp(1,n);
    int m=read();
    while(m--){
        int id=read()+1,ee=read();
        printf("%d
",ans[id][ee]);
    }
    
} 
int read(){
    int s=0,f=0;char ch=getchar();
    while(!isdigit(ch))f=ch=='-',ch=getchar();
    while(isdigit(ch))s=s*10+(ch^48),ch=getchar();
    return f?-s:s;
}
/*
5 
2 3 4 
1 2 1 
4 1 2 
2 1 1 
3 2 3 
5 
1 10 
2 7 
3 4 
4 8 
0 5
*/
View Code

ps:传统艺能:踩skyh博客

原文地址:https://www.cnblogs.com/seamtn/p/12638326.html