分治背包+单调队列优化。
但是为什么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; }