P8392 BalticOI 2022 Day1 Uplifting Excursion

贪心加动规,好题,这两个甚至完全相反的东西可以融进一道题……

思路

物品较少,贡献较小,体积较小,但总体积巨大。

直接上 \(dp\) 容易把心态搞炸。

我们可以先考虑贪心,使贡献最多还剩 \(m\)。然后考虑背包填满剩下的体积,且 \(i\) 和 \(-i\) (这里的 \(-i\) 是撤销)的物品是不会重复出现在背包中的,如果重复出现了那么肯定不优,所以最多再加入 \(2m\) 个数,背包值域开 \([-m^2,m^2]\)。

为什么这里的贪心加 \(dp\)​ 是正确的呢?

  • 由于贡献相同,贪心选体积最小的物品肯定可以选择最多。

  • 我们在贪心之后进行了 \(dp\) 调整,这个调整是可以反悔减少物品的,也就是我们的 \(f[l]\) 会在体积满足 \(l\)​ 的情况下尽可能多的增加,尽可能少的减少物品,这也是和普通背包的区别。

那么最后我们得出的答案一方面保证了体积肯定符合规定,一方面保证了贪心和动规选出的或是减少的数都是最多或最少的。

实现

我们在一开始可以先加上所有负数状态,后面的正数状态加入时就相当于也选择了负数。

    scanf("%lld%lld",&n,&l);
for(int i=n;i;i--) scanf("%lld",&a[i]),l+=a[i]*i,ans+=a[i];
int t;
scanf("%lld",&t);ans+=t;
for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
if(l<0){printf("impossible");return 0;}
for(int i=1;i<=n;i++)
{
if(b[i]*i<=l) l-=b[i]*i,ans+=(b1[i]=b[i]);
else {b1[i]=l/i;ans+=b1[i];l-=b1[i]*i;break;}
}
for(int i=n;i;i--)
{
if(a[i]*i<=l) l-=a[i]*i,ans-=(a1[i]=a[i]);
else {a1[i]=l/i;ans-=a1[i];l-=a1[i]*i;break;}
}

\(a1,b1\) 记录了选择了多少。

背包可以写成函数的形式并使用二进制优化。

void ins(ll s,ll v,ll w)//s ->数量,v ->体积,w ->贡献
{
s=min(s,n*2+1);
if(v>0)
{
int c=1;
for(;c+c<s;c<<=1,v<<=1,w<<=1);
while(1)
{
for(int i=k-v;i>=0;i--) f[i+v]=max(f[i+v],f[i]+w);
s-=c;
if(c==1) break;
c>>=1,v>>=1,w>>=1;
}
if(s>0)
{
v*=s,w*=s;
for(int i=k-v;i>=0;i--) f[i+v]=max(f[i+v],f[i]+w);
}
}
else
{
v=-v;
int c=1;
for(;c+c<s;c<<=1,v<<=1,w<<=1);
while(1)
{
for(int i=v;i<=k;i++) f[i-v]=max(f[i-v],f[i]+w);
s-=c;
if(c==1) break;
c>>=1,v>>=1,w>>=1;
}
if(s>0)
{
v*=s,w*=s;
for(int i=v;i<=k;i++) f[i-v]=max(f[i-v],f[i]+w);
}
}
}

CODE

#include<bits/stdc++.h>
using namespace std; #define ll long long
#define int long long const int maxn=505; ll l,n,m,k,ans;
ll a[maxn],b[maxn],a1[maxn],b1[maxn];
ll f[maxn*maxn*2]; void ins(ll s,ll v,ll w)
{
s=min(s,n*2+1);
if(v>0)
{
int c=1;
for(;c+c<s;c<<=1,v<<=1,w<<=1);
while(1)
{
for(int i=k-v;i>=0;i--) f[i+v]=max(f[i+v],f[i]+w);
s-=c;
if(c==1) break;
c>>=1,v>>=1,w>>=1;
}
if(s>0)
{
v*=s,w*=s;
for(int i=k-v;i>=0;i--) f[i+v]=max(f[i+v],f[i]+w);
}
}
else
{
v=-v;
int c=1;
for(;c+c<s;c<<=1,v<<=1,w<<=1);
while(1)
{
for(int i=v;i<=k;i++) f[i-v]=max(f[i-v],f[i]+w);
s-=c;
if(c==1) break;
c>>=1,v>>=1,w>>=1;
}
if(s>0)
{
v*=s,w*=s;
for(int i=v;i<=k;i++) f[i-v]=max(f[i-v],f[i]+w);
}
}
} signed main()
{
scanf("%lld%lld",&n,&l);
for(int i=n;i;i--) scanf("%lld",&a[i]),l+=a[i]*i,ans+=a[i];
int t;
scanf("%lld",&t);ans+=t;
for(int i=1;i<=n;i++) scanf("%lld",&b[i]);
if(l<0){printf("impossible");return 0;}
for(int i=1;i<=n;i++)
{
if(b[i]*i<=l) l-=b[i]*i,ans+=(b1[i]=b[i]);
else {b1[i]=l/i;ans+=b1[i];l-=b1[i]*i;break;}
}
for(int i=n;i;i--)
{
if(a[i]*i<=l) l-=a[i]*i,ans-=(a1[i]=a[i]);
else {a1[i]=l/i;ans-=a1[i];l-=a1[i]*i;break;}
}
m=n*n,k=m*2;
memset(f,0xcf,sizeof(f));
f[m]=0;
for(int i=1;i<=n;i++)
{
if(b1[i]) ins(b1[i],-i,-1);
if(b[i]-b1[i]) ins(b[i]-b1[i],i,1);
if(a1[i]) ins(a1[i],-i,1);
if(a[i]-a1[i]) ins(a[i]-a1[i],i,-1);
}
if(l>m||f[m+l]<-m){printf("impossible");return 0;}
else printf("%lld",ans+f[m+l]);
}

记得全开 long long

P8392 BalticOI 2022 Day1 Uplifting Excursion的更多相关文章

  1. LOJ#2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On

    题目描述 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会.有 N×M 个这样 ...

  2. P6739 [BalticOI 2014 Day1] Three Friends 题解

    目录 写在前面 Solution 何为字符串哈希(可跳过): Code 写在前面 P6739 [BalticOI 2014 Day1] Three Friends 听说这题可以用比较暴力的做法过,比如 ...

  3. luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers

    目录 luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers 简述题意: Solution: Code luoguP6754 [BalticOI ...

  4. P6753 [BalticOI 2013 Day1] Ball Machine

    P6753 [BalticOI 2013 Day1] Ball Machine 题意 给你一个树,每次从根节点放一个求,如果其子节点有空这个球会向下滚,若有多个节点为空则找儿子中以子树内编号的最小值为 ...

  5. P4675 [BalticOI 2016 day1]Park (并查集)

    题面 在 Byteland 的首都,有一个以围墙包裹的矩形公园,其中以圆形表示游客和树. 公园里有四个入口,分别在四个角落( 1 , 2 , 3 , 4 1, 2, 3, 4 1,2,3,4 分别对应 ...

  6. 「JOISC 2022 Day1」京都观光 题解

    Solution 考虑从\((x_1,y_1)\)走到\((x_2,y_2)\)满足只改变一次方向,则容易求出先向南走当且仅当 \[\frac{a_{x_1} - a_{x_2}}{x_1 - x_2 ...

  7. LOJ 一本通一句话题解系列:

    第一部分 基础算法 第 1 章 贪心算法 1):「一本通 1.1 例 1」活动安排:按照结束时间排序,然后扫一遍就可以了. 2):「一本通 1.1 例 2」种树:首先要尽量的往区间重叠的部分种树,先按 ...

  8. 【搜索 ex-BFS】bzoj2346: [Baltic 2011]Lamp

    关于图中边权非零即一的宽度优先搜索 Description 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组 ...

  9. 电路维修 (广搜变形-双端队列bfs)

    # 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...

  10. LOJ2632

    题目描述 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会.有  个这样的元件 ...

随机推荐

  1. Linux下常用组件镜像源、smaba、gcc、ssh、mysql安装

    Linux安装 博主使用的是ubuntu 16.04 apt更换镜像源 这里以更换阿里云镜像源为例. 首先去阿里云官方网站找对应版本系统的镜像源https://developer.aliyun.com ...

  2. portainer控制多个docker

    打开docker的远程访问(参考下方博客) 觉得不安全可以配置 使用 TLS 加密 https://www.cnblogs.com/hongdada/p/11512901.html 使用新版本port ...

  3. history的replace("/admin")与("admin")的区别

    假设当前路由为:localhost:3000/index/a 有"/"的情况是直接从根目录替换 改完之后的路由为:localhost:3000/admin 没有"/&qu ...

  4. cesium的使用

    安装 建议使用vue的cesium插件:vue-cli-plugin-cesium.vue add命令可零配置添加cesium:vue add vue-cli-plugin-cesium 报错 添加完 ...

  5. mybatis springboot多数据源,根据使用的数据库不同,执行不同的sql语句

    springboot 多数据源配置就不说了,百度太多的用例, 这里只说下在多数据源下切换执行sql逻辑 1.xml sql嵌套,通过<if>标签来判断,用的是mybatis自己sql动态拼 ...

  6. 关于.NET在中国为什么工资低的分析

    引言 近年来,随着软件开发行业的蓬勃发展,越来越多的编程语言和框架进入了市场,成为了不同类型软件开发项目的首选工具.然而,在中国的开发者社区中,.NET 开发人员的工资水平相比其他技术栈,如 Java ...

  7. SQL无法解决排序规则 Chinese_PRC_CI_AS 和 Latin1_General_CI_AS 的冲突

    最近在执行一些跨库关联查询语句的时候提示了 "Cannot resolve the collatior conflict between "Chinese_PRC_Ci As&qu ...

  8. CIIS 2023 丨聚焦文档图像处理前沿领域,合合信息 AI 助力图像处理与内容安全保障

    近日,2023第十二届中国智能产业高峰论坛(CIIS 2023)在江西南昌顺利举行.大会由中国人工智能学会.江西省科学技术厅.南昌市人民政府主办,南昌市科学技术局.中国工程科技发展战略江西研究院承办. ...

  9. 升讯威在线客服系统如何高性能同时支持 MySQL 和 SQL Server

    升讯威在线客服与营销系统是基于 .net core / WPF 开发的一款在线客服软件,宗旨是: 开放.开源.共享.努力打造 .net 社区的一款优秀开源产品. 前段时间我发表了一系列文章,开始介绍基 ...

  10. PasteForm最佳CRUD实践,实际案例PasteTemplate详解之3000问(二)

    作为"贴代码"力推的一个CRUD实践项目PasteTemplate,在对现有的3个项目进行实战后效果非常舒服!下面就针对PasteForm为啥我愿称为最佳CRUD做一些回答: 哪里 ...