标签:max 题目 int luogu mid 40039 flag P6240 dp
题面传送门
一句话题面:区间01背包。
这种东西可以用分治解决掉。
发现如果完全合并两个dp状态是\(O(t^2)\)的,但是如果只是针对某一个值的合并只是\(O(t)\)的。所以这题中不能进行合并状态。
预处理线段树上每个节点\(l\)到\(mid\)与\(mid+1\)到\(r\)的两部分\(dp\)状态。
在一棵线段树上,将所有询问推到不能再推时,即如果再推会分成两个询问时,合并两边的\(dp\)状态来得出答案。
时间复杂度\(O(ntlogn+mt)\)
代码实现:
#include<cstdio>
#include<cstring>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,k,x,y,z,dp[40039][239],a[40039],b[40039],mid,maxt,flag;
struct yyy{int x,y,l,r,z,flag,ans;}f[200039];
int main(){
// freopen("1.in","r",stdin);
register int i,j,h;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=n;i++) scanf("%d",&b[i]);
for(i=1;i<=m;i++) scanf("%d%d%d",&f[i].x,&f[i].y,&f[i].z),f[i].l=1,f[i].r=n,maxt=max(maxt,f[i].z);
while(1){
memset(dp,-0x3f,sizeof(dp));
for(i=1;i<=m;i++){
if(f[i].flag) continue;
mid=f[i].l+f[i].r>>1;
if(dp[mid][0]<=-1e9){
for(j=0;j<a[mid];j++) dp[mid][j]=0;
for(j=a[mid];j<=maxt;j++) dp[mid][j]=b[mid];
if(f[i].l<=mid-1){
for(j=mid-1;j>=f[i].l;j--){
for(h=0;h<=maxt;h++){
dp[j][h]=dp[j+1][h];
if(h>=a[j]) dp[j][h]=max(dp[j][h],dp[j+1][h-a[j]]+b[j]);
}
}
}
if(mid+1<=f[i].r){
for(j=0;j<a[mid+1];j++) dp[mid+1][j]=0;
for(j=a[mid+1];j<=maxt;j++) dp[mid+1][j]=b[mid+1];
for(j=mid+2;j<=f[i].r;j++){
for(h=0;h<=maxt;h++){
dp[j][h]=dp[j-1][h];
if(h>=a[j]) dp[j][h]=max(dp[j][h],dp[j-1][h-a[j]]+b[j]);
}
}
}
}
} flag=0;
for(i=1;i<=m;i++){
if(f[i].flag) continue;
flag=1;mid=f[i].l+f[i].r>>1;
if(f[i].l==f[i].r){f[i].ans=dp[mid][f[i].z];f[i].flag=1;continue;}
if(f[i].y<=mid) f[i].r=mid;
else if(f[i].x>mid) f[i].l=mid+1;
else{
for(j=0;j<=f[i].z;j++) f[i].ans=max(f[i].ans,dp[f[i].x][j]+dp[f[i].y][f[i].z-j]);
f[i].flag=1;
}
}
if(!flag) break;
}
for(i=1;i<=m;i++) printf("%d\n",f[i].ans);
}
标签:max,题目,int,luogu,mid,40039,flag,P6240,dp 来源: https://www.cnblogs.com/275307894a/p/14223519.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。