HDU5808(Bestcoder Round86)Price List Strike Back

本文介绍了一种解决背包问题的有效算法,通过使用bitset优化区间更新和查询操作,实现了高效的求解过程。此外,还探讨了如何利用分治策略进一步简化问题。

题目戳这

假如我们已知第i天可以购买的所有商品,那么剩下就是01背包的问题了.能够购买的所有商品由两个条件决定:编号下标和距离.我们可以减少一个维度使问题更简单.

假如把询问和点一起按照距离d排序,那么就能保证询问到i时,所有考虑到的点x一定满足 dis[x]<=di 这一条件.

现在问题就转化成了:

询问:在 [Li,Ri] 区间中能否找到一些点满足其价值之和= sumi .

更新:点x的价值为 val[x] .

对于区间问题,可以考虑线段树求解.既然询问价值和的可能性,而且 sumi100 ,那么我们可以用一个bool数组h,记录这个区间所有能够取到的价值和,作为一个区间的状态.

对于单点更新x操作:

对每个经过x的区间用 O(sum) 的复杂度更新h数组.

对区间查询 [l,r] 操作:

O(sum2) 的复杂度对两个区间进行合并.

最终的复杂度为: O(mlogn10000+nlogn100) ,你会发现它和暴力没有什么差别T T.

这里有一个大优化!
对于单点更新x操作:
对于更新前 每个的 h[j]=1 可以保证更新后 得到: h[j]=1 , h[j+val[x]]=1 .
假如我们把h数组看成一个01串,那么 h[j]=1 => h[j+val[x]]=1 可以把答案看作把这个串整体移动 val[x] 位再按位或上更新前的01串的结果.

对于区间合并:

假设当前区间的01串为a1,两个儿子的01串分别为a2,a3.

a1|=a2.

a1|=a3.

对于a3的每个值为1的位i: a1|=a2<<i

那有什么能够高效地完成以上二进制的操作?!

bitset!!

它相当于把64位的数字接在一起,形成一个01串,并且支持二进制的所有运算,比如按位或,位移等.

复杂度: O(len/64) .len表示01串的长度.

用bitset完成操作后,时间复杂度为:

O(mlognsumsum/64+nlognsum/64) .

当然这种思路有一个神奇的解法:

可用BIT求一个区间内每个商品的个数.

商品的种类最多只有100种,而每种商品的数量却很多,这种情况可以选择多重背包进行优化.把物品总数减少到 100logn .在dp时依然可以用bitset优化,效果显著!!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bitset>
using namespace std;
const int M=105;
int n,m;
int ans[100005];
int id=0,l,r,c,sum;
bitset<M>dp;
inline void rd(int &res){
    char c;res=0;
    while(c=getchar(),c<48);
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),c>47);
}
struct node{
    int v,d,id;
}A[20005];
struct LZ{
    int l,r,d,sum,id;
}Q[100005];
int bit[20005][105];
void add(int x,int y){
    while(x<=n){
        bit[x][y]++;
        x+=x&-x;
    }
}
int query(int x,int y){
    int sum=0;
    while(x){
        sum+=bit[x][y];
        x^=x&-x;
    }
    return sum;
}
bool cmp(node a,node b){return a.d<b.d;}
bool cmp1(LZ a,LZ b){return a.d<b.d;}
int val[20005];
int main(){
    int cas;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)rd(A[i].v);
        for(int i=1;i<=n;i++)rd(A[i].d),A[i].id=i;
        sort(A+1,A+n+1,cmp);
        for(int i=1;i<=m;i++){
            ans[i]=0;
            rd(Q[i].l);
            rd(Q[i].r);
            rd(Q[i].d);
            rd(Q[i].sum);Q[i].id=i;
        }
        sort(Q+1,Q+m+1,cmp1);
        int x=1;
        for(int i=1;i<=m;i++){
            while(x<=n&&A[x].d<=Q[i].d){
                add(A[x].id,A[x].v);
                x++;
            }
            int can=query(Q[i].r,Q[i].sum)-query(Q[i].l-1,Q[i].sum);
            if(can){ans[Q[i].id]=0;}
            else{
                dp.reset();
                dp[0]=1;
                int cnt=0;
                for(int j=1;j<Q[i].sum;j++){
                    int s=query(Q[i].r,j)-query(Q[i].l-1,j),p=1;
                    while(p<s){
                        val[++cnt]=p*j;
                        s-=p;
                        p<<=1;
                    }
                    if(s)val[++cnt]=s*j;
                }
                for(int j=1;j<=cnt;j++){
                    dp|=dp<<val[j];
                    if(dp[Q[i].sum])break;
                }
                if(!dp[Q[i].sum])ans[Q[i].id]=1;
            }
        }
        for(int i=1;i<=m;i++)putchar(ans[i]^48);
    return 0;
}

当然最稳(qi)定(pa)的正解的思路是分治!

官方题解传送门: http://bestcoder.hdu.edu.cn/

对于 [L,R] 区间内的所有询问,我们可以分为 [L,mid][mid+1,R] 两个区间,对于左右端点都在左区间或者都在右区间的询问递归求解.

那么现在只要回答左端点在左区间,右端点在右区间的询问.

假设 dpl[i][j] 表示 [I,mid] 达到价值和为j的最大距离最小值.

dpr[i][j] 表示 [mid+1,r] 达到价值为j的最大距离最小值.

可以用 (rl+1)sum 的复杂度处理出以上两个数组,对于每个询问,找到 [li,ri] 区间内到达sumi的最大距离的最小值 a ,再与di进行判断就可以得到答案.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=1e5+5;
const int N=2e4+5;
const int S=105;
const int oo=1e9+5;
struct node{
    int id,l,r,sum,d;
}Q[M];
inline void rd(int &res){
    res=0; char c;
    while (c=getchar(),c<48);
    do{
        res=(res<<3)+(res<<1)+(c^48);
    }while (c=getchar(),c>=48);
}
bool cmp(node a,node b){
    if(a.l!=b.l)return a.l<b.l;
    return a.r<b.r;
}
int dp[S][N],res[M],val[N],n,m,dis[N],q[M],st[N];
void solve(int L,int R){//Q.l<=mid;Q.r>=mid
    int mid=L+R>>1,i,j,tot=0;
    if(L==R){
        for(i=st[L];i<=st[R+1]-1;i++){
            if(Q[i].r==Q[i].l&&Q[i].l==L)q[++tot]=i;
        }
        for(i=1;i<=tot;i++){
            int id=q[i];
            if(Q[id].d>=dis[L]&&Q[id].sum==val[L])res[Q[id].id]=0;
            else res[Q[id].id]=1;
        }
        return ;
    }
    for(i=st[L];i<=st[mid+1]-1;i++){
        if(Q[i].r>mid&&Q[i].r<=R)q[++tot]=i;
    }
    if(tot){
        for(i=L;i<=R;++i){
            for(j=1;j<S;++j)dp[j][i]=oo;
            dp[0][i]=0;
        }
        dp[val[mid]][mid]=dis[mid];
        dp[val[mid+1]][mid+1]=dis[mid+1];
        for(i=mid-1;i>=L;--i){//dp[i][j]表示[i,mid]区间中,得到j 最远距离的最小值 
            for(j=0;j<S;++j){    
                dp[j][i]=dp[j][i+1];
                if(j>=val[i])dp[j][i]=min(dp[j][i],max(dp[j-val[i]][i+1],dis[i]));
            }
        }
        for(i=mid+2;i<=R;++i){
            for(j=0;j<S;++j){
                dp[j][i]=dp[j][i-1];
                if(j>=val[i])dp[j][i]=min(dp[j][i],max(dp[j-val[i]][i-1],dis[i]));
            }
        }
        for(i=1;i<=tot;++i){//横跨mid的询问 
            int id=q[i];
            int mi=oo,l=Q[id].l,r=Q[id].r,sum=Q[id].sum;
            for(j=0;j<=Q[id].sum;++j){
                mi=min(mi,max(dp[j][l],dp[sum-j][r]));
            }
            if(mi<=Q[id].d)res[Q[id].id]=0;
            else res[Q[id].id]=1;
        }
    }
    solve(L,mid);
    solve(mid+1,R);
}
int find(int x){//Q[i].l>=x 
    int l=1,r=m,res=m+1;
    while(l<=r){
        int mid=l+r>>1;
        if(Q[mid].l>=x){
            r=mid-1;
            res=mid;
        }else l=mid+1;
    }return res;
}
int main(){
    int i,j,k,cas,a,b,c;
    rd(n);rd(m);
    for(i=1;i<=n;i++)rd(val[i]);
    for(i=1;i<=n;i++)rd(dis[i]);
    for(i=1;i<=m;i++){
        rd(Q[i].l);rd(Q[i].r);rd(Q[i].d);rd(Q[i].sum);
        Q[i].id=i;
    }
    sort(Q+1,Q+1+m,cmp);
    for(i=1;i<=n;i++){//st[i]表示L>=i的第一个询问的下标 
        st[i]=find(i);
    }
    st[n+1]=m+1;
    solve(1,n);
    for(i=1;i<=m;i++){
        if(res[i])putchar('1');
        else putchar('0');
    }
    puts("");

    return 0;
}
源码地址: https://pan.quark.cn/s/a4b39357ea24 欧姆龙触摸屏编程软件MPTST 5.02是专门为欧姆龙品牌的工业触摸屏而研发的编程解决方案,它赋予用户在直观界面上构建、修改以及排错触摸屏应用程序的能力。 该软件在工业自动化领域具有不可替代的地位,特别是在生产线监视、设备操控以及人机互动系统中发挥着核心作用。 欧姆龙MPTST(Machine Process Terminal Software Touch)5.02版本配备了多样化的功能,旨在应对不同种类的触摸屏项目要求。 以下列举了若干核心特性:1. **图形化编程**:MPTST 5.02采用图形化的编程模式,允许用户借助拖拽动作来设计屏幕布局,设定按钮、滑块、指示灯等组件,显著简化了编程流程,并提升了工作效率。 2. **兼容性**:该软件能够适配欧姆龙的多个触摸屏产品线,包括CX-One、NS系列、NJ/NX系列等,使用户可以在同一个平台上完成对不同硬件的编程任务。 3. **数据通信**:MPTST 5.02具备与PLC(可编程逻辑控制器)进行数据交互的能力,通过将触摸屏作为操作界面,实现生产数据的显示与输入,以及设备状态的监控。 4. **报警与事件管理**:软件中集成了报警和事件管理机制,可以设定多种报警标准,一旦达到预设条件,触摸屏便会展示对应的报警提示,助力操作人员迅速做出响应。 5. **模拟测试**:在设备实际连接之前,MPTST 5.02支持用户进行脱机模拟测试,以此验证程序的正确性与稳定性。 6. **项目备份与恢复**:为了防止数据遗失,MPTST 5.02提供了项目文件的备份及还原功能,对于多版本控制与团队协作具有显著价值。 7. **多语言支持**:针对全球化的应...
本资源包为流体力学与化学传质交叉领域的研究提供了一套完整的数值模拟解决方案,重点针对湍流条件下通道内溶解物质的输运与分布规律进行定量分析。该工具集专为高等院校理工科专业的教育与科研需求设计,尤其适合计算机科学、电子工程及数学等相关学科的本科生在完成课程项目、综合设计或学位论文时使用。 软件环境兼容多个版本的MatLAB平台,包括2014a、2019b及后续的2024b发行版,确保了在不同实验室或个人计算环境中的可移植性。资源包内预置了经过验证的示例数据集,用户可直接调用主程序执行计算,显著降低了初始学习成本,使初学者能够迅速掌握基本操作流程。 代码架构采用模块化与参数驱动设计。所有关键物理参数(如流速、扩散系数、边界条件等)均集中于独立的配置模块,用户无需深入底层算法即可灵活调整计算条件,从而高效模拟多种湍流溶解场景。程序逻辑结构清晰,各功能段均配有详尽的说明注释,既阐述了数值方法的理论依据,也解释了关键步骤的实现意图,便于使用者理解模型构建过程并进行针对性修改。 在学术训练方面,本工具能够帮助学生将抽象的流体动力学与传质理论转化为可视化的数值实验结果,深化对湍流混合、浓度边界层等概念的理解。对于毕业设计或专题研究,其参数化框架支持用户嵌入自定义模型,开展创新性数值实验,为深入研究复杂流动中的溶解机制提供可靠的技术支撑。 总体而言,该MATLAB分析工具集通过结构化的代码设计、完备的案例支持与广泛的版本兼容性,为流体溶解现象的数值研究提供了一个高效、可扩展的计算平台,兼具教学示范与科研探索的双重价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
标题JSPM自行车个性化改装推荐系统研究AI更换标题第1章引言介绍自行车个性化改装推荐系统的研究背景、意义及国内外研究现状。1.1研究背景与意义阐述自行车个性化改装需求增长及推荐系统的重要性。1.2国内外研究现状分析国内外自行车改装推荐系统的研究进展及不足。1.3研究方法及创新点概述JSPM系统的设计方法及相较于其他系统的创新点。第2章相关理论介绍与自行车个性化改装推荐系统相关的理论基础。2.1个性化推荐理论阐述个性化推荐的基本原理和常用算法。2.2自行车改装知识介绍自行车结构、部件及改装选项等基础知识。2.3用户偏好分析理论讨论如何分析用户偏好以实现精准推荐。第3章JSPM系统设计详细介绍JSPM自行车个性化改装推荐系统的设计方案。3.1系统架构设计阐述系统的整体架构、模块划分及功能。3.2数据库设计介绍系统数据库的设计思路、表结构及关系。3.3推荐算法设计详细介绍基于用户偏好的推荐算法实现过程。第4章系统实现与测试介绍JSPM系统的实现过程及测试方法。4.1系统开发环境与工具说明系统开发所使用的环境、工具及技术栈。4.2系统实现过程阐述系统从设计到实现的具体步骤和关键代码。4.3系统测试与优化介绍系统的测试方法、测试结果及优化措施。第5章研究结果与分析展示JSPM系统的实验分析结果并进行讨论。5.1实验数据与指标介绍实验所采用的数据集、评估指标及实验环境。5.2实验结果展示通过图表等形式展示实验结果,包括推荐准确率等。5.3结果分析与讨论对实验结果进行详细分析,讨论系统的优缺点及改进方向。第6章结论与展望总结JSPM自行车个性化改装推荐系统的研究成果并展望未来。6.1研究结论概括本文的主要研究成果,包括系统设计、实现及实验结果。6.2展望指出系统存在的不足,提出未来研究的方向和改进措施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值