BZOJ 3163 Eden的新背包问题

分治背包+单调队列优化。

但是为什么maxn要1w多?。。。不怎么懂。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cstdlib>
#define maxn 10050
#define maxs 1050
#define maxm 300500
using namespace std;
int n,x,y,z,m,ans[maxm],up[maxn],q[maxn],vals[maxn],l,r;
struct point
{
    int l,r,v,w,c;
    point (int l,int r,int v,int w,int c):l(l),r(r),v(v),w(w),c(c){}
};
vector <point> v;
vector <int> dp,linker[maxn],val[maxn];
int read()
{
    int data=0;char ch;
    while (ch<‘0‘ || ch>‘9‘) ch=getchar();
    while (ch>=‘0‘ && ch<=‘9‘)
    {
        data=data*10+ch-‘0‘;
        ch=getchar();
    }
    return data;
}
void insert(int x,int y,int v,int w,vector <int> & dp)
{
    while ((l<=r) && (vals[r]<=dp[x]-y*w)) r--;
    q[++r]=x;vals[r]=dp[x]-y*w;
}
void DC(int left,int right,vector <point> v,vector <int> dp)
{
    int mid=left+right>>1;
    vector <point> x,y;
    for (int i=0;i<v.size();i++)
    {
        point now=v[i];
        if ((now.l==left) && (now.r==right))
        {
            for (int j=0;j<=maxs%now.v;j++) up[j]=maxs/now.v*now.v+j;
            for (int j=maxs%now.v+1;j<now.v;j++) up[j]=(maxs/now.v-1)*now.v+j;
            for (int j=0;j<now.v;j++)
            {
                l=1;r=0;int ret=up[j],lim=up[j],ret1=up[j]/now.v,ret2=up[j]/now.v;
                while (ret>=0)
                {
                    while ((l<=r) && (q[l]>ret)) l++;
                    while ((lim>=ret-now.c*now.v) && (lim>=0))
                    {
                        insert(lim,ret2,now.v,now.w,dp);
                        lim-=now.v;ret2--;
                    }
                    dp[ret]=vals[l]+ret1*now.w;
                    ret1--;ret-=now.v;
                }
            }
        }
        else if (now.r<=mid) x.push_back(now);
        else if (now.l>=mid+1) y.push_back(now);
        else
        {
            x.push_back(point(now.l,mid,now.v,now.w,now.c));
            y.push_back(point(mid+1,now.r,now.v,now.w,now.c));
        }
    }
    if (left==right)
    {
        for (int i=0;i<linker[left].size();i++)
            ans[linker[left][i]]=dp[val[left][i]];
        return;
    }
    DC(left,mid,x,dp);
    DC(mid+1,right,y,dp);
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++)
    {
        x=read();y=read();z=read();
        if (i!=1) v.push_back(point(1,i-1,x,y,z));
        if (i!=n) v.push_back(point(i+1,n,x,y,z));
    }
    for (int i=0;i<=maxn;i++) dp.push_back(0);
    m=read();
    for (int i=1;i<=m;i++)
    {
        x=read();y=read();x++;
        linker[x].push_back(i);val[x].push_back(y);
    }
    DC(1,n,v,dp);
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}
时间: 2024-10-07 01:17:22

BZOJ 3163 Eden的新背包问题的相关文章

【BZOJ】【3163】【HEOI2013】Eden的新背包问题

多重背包/思路题 多次询问,每次从所有物品中忽略一件,问最大收益…… 这题我用的zyf的一个“暴力”做法,就是先预处理出来g1[i][j]表示1~i号物品花了j块钱的最大价值,g2[i][j]表示i~n号物品花了j块钱的最大价值(这里我将所有的物品编号都加了1,原因……因为我一开始没+1,WA了QAQ) 然后询问的时候$ans=max_{j=0}^{e}\{ans,g1[d-1][j]+g2[d+1][e-j]\}$ 因为编号是0~n-1,所以这里$d-1$这一项是会越界的!不知为什么在CH上过

BZOJ3163&amp;Codevs1886: [Heoi2013]Eden的新背包问题[分治优化dp]

3163: [Heoi2013]Eden的新背包问题 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 428  Solved: 277[Submit][Status][Discuss] Description “寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听.”失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她的音容笑貌. 记忆中,她总是喜欢给Eden出谜题:在 valent

BZOJ 3163 Heoi2013 Eden的新背包问题 多重背包

题目大意:多重背包,多次询问某个物品不能选择时以某个总价钱最多能获得多少价值 求问正解是啥QAQ 维护一个前缀多重背包和一个后缀多重背包 每次询问时 枚举前面选多少和后面选多少 暴力统计答案即可 时间复杂度O(n^2logn+nq) 这3E的复杂度居然只跑了600sQAQ 正解到底是啥QAQ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #defin

bzoj3163: [Heoi2013]Eden的新背包问题

Description “寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听.”失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她的音容笑貌. 记忆中,她总是喜欢给Eden出谜题:在 valentine’s day 的夜晚,两人在闹市中闲逛时,望着礼品店里精巧玲珑的各式玩偶,她突发奇想,问了 Eden这样的一个问题:有n个玩偶,每个玩偶有对应的价值.价钱,每个玩偶都可以被买有限次,在携带的价钱m固定的情况下,如何选择买哪些玩偶

DSY3163*Eden的新背包问题

Description "寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听."失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她的音容笑貌. 记忆中,她总是喜欢给Eden出谜题:在 valentine's day 的夜晚,两人在闹市中闲逛时,望着礼品店里精巧玲珑的各式玩偶,她突发奇想,问了 Eden这样的一个问题:有n个玩偶,每个玩偶有对应的价值.价钱,每个玩偶都可以被买有限次,在携带的价钱m固定的情况下,如何选择

[HEOI2013]Eden 的新背包问题

题目描述 " 寄 没 有 地 址 的 信 ,这 样 的 情 绪 有 种 距 离 ,你 放 着 谁 的 歌 曲 ,是 怎 样 的 心 情 . 能 不 能 说 给 我 听 ." 失忆的 Eden 总想努力地回忆起过去,然而总是只能清晰地记得那种思念的 感觉,却不能回忆起她的音容笑貌. 记忆中,她总是喜欢给 Eden 出谜题:在 valentine's day 的夜晚,两人在闹市 中闲逛时,望着礼品店里精巧玲珑的各式玩偶,她突发奇想,问了 Eden 这样的 一个问题:有 n 个玩偶,每个玩偶

Luogu P4095 [HEOI2013]Eden 的新背包问题 思维/动规

当时一直在想前缀和...多亏张队提醒... 从1到n背次包,保存每一个状态下的价值,就是不要把第一维压掉:再从n到1背一次,同样记住每种状态: 然后询问时相当于是max(前缀+后缀),当然前缀后缀中间去掉了一个应去掉的商品. #include<cstdio> #include<iostream> #define R register int using namespace std; inline int g() { R ret=0,fix=1; register char ch;

[题解](背包)luogu_P4095 eden的新背包问题

有一点乱搞吧......对人对背包的理解有些考验,要想知道去掉某个点的值,可以选择对前缀求一次背包,后缀求一次背包,而且不省掉价钱那一维, 这样每个点就可以由前后组合成了,枚举一下价钱取max即可 直接01的多重背包就可以过 #include<bits/stdc++.h> using namespace std; const int maxn=1010; int n,m,q,ans,v[maxn],w[maxn],c[maxn]; int f[maxn][maxn],g[maxn][maxn]

Luogu P4095 [HEOI2013] Eden的新背包问题

题目 求出从前往后的背包\(f_{i,j}\)和从后往前的背包\(F_{i,j}\). 那么对于询问\((d,e)\),答案就是\(\max\limits_{i=0}^e f_{d-1,i}+F_{d+1,e-i}\). 然后就是单调队列优化多重背包. 我们知道多重背包的转移\(f[i][j]=\max\limits_{k=0}^{min(c[i],\lfloor\frac j{w[i]}\rfloor)}(f[i-1][j-w[i]*k]+v[i]*k)\) 令\(s=\lfloor\frac