P8392 BalticOI 2022 Day1 Uplifting Excursion
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的更多相关文章
- LOJ#2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On
题目描述 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会.有 N×M 个这样 ...
- P6739 [BalticOI 2014 Day1] Three Friends 题解
目录 写在前面 Solution 何为字符串哈希(可跳过): Code 写在前面 P6739 [BalticOI 2014 Day1] Three Friends 听说这题可以用比较暴力的做法过,比如 ...
- luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers
目录 luoguP6754 [BalticOI 2013 Day1] Palindrome-Free Numbers 简述题意: Solution: Code luoguP6754 [BalticOI ...
- P6753 [BalticOI 2013 Day1] Ball Machine
P6753 [BalticOI 2013 Day1] Ball Machine 题意 给你一个树,每次从根节点放一个求,如果其子节点有空这个球会向下滚,若有多个节点为空则找儿子中以子树内编号的最小值为 ...
- P4675 [BalticOI 2016 day1]Park (并查集)
题面 在 Byteland 的首都,有一个以围墙包裹的矩形公园,其中以圆形表示游客和树. 公园里有四个入口,分别在四个角落( 1 , 2 , 3 , 4 1, 2, 3, 4 1,2,3,4 分别对应 ...
- 「JOISC 2022 Day1」京都观光 题解
Solution 考虑从\((x_1,y_1)\)走到\((x_2,y_2)\)满足只改变一次方向,则容易求出先向南走当且仅当 \[\frac{a_{x_1} - a_{x_2}}{x_1 - x_2 ...
- LOJ 一本通一句话题解系列:
第一部分 基础算法 第 1 章 贪心算法 1):「一本通 1.1 例 1」活动安排:按照结束时间排序,然后扫一遍就可以了. 2):「一本通 1.1 例 2」种树:首先要尽量的往区间重叠的部分种树,先按 ...
- 【搜索 ex-BFS】bzoj2346: [Baltic 2011]Lamp
关于图中边权非零即一的宽度优先搜索 Description 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组 ...
- 电路维修 (广搜变形-双端队列bfs)
# 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...
- LOJ2632
题目描述 译自 BalticOI 2011 Day1 T3「Switch the Lamp On」有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会.有 个这样的元件 ...
随机推荐
- ServletConfig 类和ServletContext 类
ServletConfig 类 ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类. Servlet 程序和 ServletConfig 对象都是由 Tomcat ...
- 单个48TB大小SQL Server数据库备份导致日志文件无法截断
单个48TB大小SQL Server数据库备份导致日志文件无法截断 SQL Server 版本:SQL Server 2019背景在一个48T大小的单数据库环境中,采用简单恢复模式,日志文件大小限制为 ...
- nacos未授权访问漏洞,导致被网警找
背景 公司收购了另一家公司,所以相应的后端服务和服务器都交给我管理,但是没有任何的交接文档,大概看了一下代码,依赖的东西就去忙别的了. 直到今天网警突然打电话给我说系统有漏洞(CVE-2021-294 ...
- 【论文解读】Faster sorting algorithm
一.简要介绍 基本的算法,如排序或哈希,在任何一天都被使用数万亿次.随着对计算需求的增长,这些算法的性能变得至关重要.尽管在过去的2年中已经取得了显著的进展,但进一步改进这些现有的算法路线的有 ...
- "放开那代码让我来!"——Cursor帮你写代码的奇妙之旅
让我们开门见山:编程很酷,但也很折磨人.那些长时间盯着屏幕,debug无休止的日子,只有程序员懂得它的酸爽.而就在这个编程焦虑的世界中,Cursor横空出世,带着一系列魔法功能,如同你手中的一根智能魔 ...
- 使用ValueConverters扩展实现枚举控制页面的显示
1.ValueConverters 本库包含了IValueConverter接口的的最常用的实现,ValueConverters用于从视图到视图模型的值得转换,某些情况下,可用进行反向转换.里面有一些 ...
- 开源的键鼠共享工具「GitHub 热点速览」
十一长假回来,我的手放在落灰的键盘上都有些陌生了,红轴竟敲出了青轴般的响声,仿佛在诉说对假期结束的不甘. 假期回归的首更,让我们看看又有什么好玩的开源项目冲上了开源热榜.一套键盘和鼠标控制多台电脑的工 ...
- 2022年2月国产数据库排行榜:冠军宝座面临挑战,OceanBase 重返 TOP3
大家好!文章开始本是用"新春快乐!虎年吉祥!"和大家打个招呼,无奈时间过得太快而文章整理得很慢,眼看崭新的三月还有几天就到来,那就在这里祝屏幕前的你在三月比二月更优秀! 月初,20 ...
- 简述 JavaScript脚本的执行原理?
js 是一种动态 . 弱类型 . 基于原型的语言 ,通过浏览器可以直接执行: 当浏览器遇到 <script></script>标记时 , 会执行标记之间的js 代码:然后js ...
- 什么是SQL注入并解决
' or ' 1 ' = ' 1 原理:通过违规的字符串改变原来的SQL语句 :[将敏感字符进行转义] // 包名 package com.zhulx.JDBC; // 导入实例类 import co ...