BZOJ 3163 Eden的新背包问题

Posted on 2016-11-11 21:45  ziliuziliu  阅读(226)  评论(0编辑  收藏  举报

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

但是为什么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;
}