题面


数据范围

1

n

5

×

1

0

5

1\leq n\leq5\times10^5

1≤n≤5×105 。

题解

n

20

n\leq 20

n≤20 的状压应该都会吧,状态记录已经选了的蛋糕集合,以及蛋糕序列的尾部奶油,然后枚举蛋糕转移。


总共有

10

10

10 种不同的蛋糕,数据很小。

把最后的蛋糕塔等效为一个序列,如果有连续三个同种蛋糕,美味度分别为

A

,

B

,

C

A,B,C

A,B,C,那么就可以把他们等效为一个美味度为

A

+

B

+

C

A+B+C

A+B+C 的同种蛋糕,放在原来的位置。于是连续的一段奇数个同种蛋糕都可以合并成一个蛋糕。

现在我们证明一个结论:存在最优解,满足对于每种蛋糕,按上述方式合并后,蛋糕数量不超过 2 个(至多两段连续奇数段)。

考虑用调整法,对于任意解中的任意一种蛋糕,合并后仍存在三个不同位置的蛋糕

a

,

b

,

c

a,b,c

a,b,c ,已知每种蛋糕都有两种方向,由鸽笼原理可得,这三块蛋糕一定至少有两块蛋糕是同向的。不妨设

a

,

b

a,b

a,b 的奶油都是 左

X

X

X 右

Y

Y

Y ,

a

<

b

a<b

a<b ,那么区间

[

a

+

1

,

b

1

]

[a+1,b-1]

[a+1,b−1] 的整体就是左

Y

Y

Y 右

X

X

X 。我们把

[

a

+

1

,

b

1

]

[a+1,b-1]

[a+1,b−1] 对称翻转,然后移开

a

,

b

a,b

a,b ,把

a

,

b

a,b

a,b 拼起来塞到

c

c

c 的一侧,最后合并

a

,

b

,

c

a,b,c

a,b,c 。整个过程结束,蛋糕序列美味度总和不变,仍然合法,

a

,

b

,

c

a,b,c

a,b,c 却变成了一块蛋糕。

既然合并后每种蛋糕可以不超过两个,那么我们就可以提前把每种蛋糕最大的前奇数个合并到一起,最多留下一个最小的,这样每种蛋糕一开始就只有两个,总的蛋糕数量

n

n

n 降至

20

20

20 ,

就可以用状压了。

CODE

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<random>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 500005
#define LL long long
#define ULL unsigned long long
#define DB double
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
#define FI first
#define SE second
LL read() {
LL f=1,x=0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<3) + (x<<1) + (s^48); s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar('0'+(x%10));}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) {putchar('-');x = -x;}
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);} int n,m,s,o,k;
const int id[4][4] = {{0,1,2,3},{1,4,5,6},{2,5,7,8},{3,6,8,9}};
priority_queue<LL> q[15];
int a[25];
LL w[25];
vector<int> bu[15];
int le[15];
LL dp[1<<20|5][4];
int main() {
freopen("cake.in","r",stdin);
freopen("cake.out","w",stdout);
n = read();
for(int i = 1;i <= n;i ++) {
k = read();
char A = ' ',B = ' ';
while(A == ' ') A = getchar();
while(B == ' ') B = getchar();
int bl = id[A-'W'][B-'W'];
q[bl].push(k);
}
for(int i = 0;i < 10;i ++) {
while((int)q[i].size() > 2) {
LL A = q[i].top();q[i].pop();
LL B = q[i].top();q[i].pop();
LL C = q[i].top();q[i].pop();
q[i].push(A+B+C);
}
while(!q[i].empty()) {
a[m] = i; w[m] = q[i].top(); q[i].pop();
bu[i].push_back(m); le[i] ++;
m ++;
}
}
int tp = (1<<m);
LL ans = 0;
for(int i = 1;i < tp;i ++) {
for(int j = 0;j < 4;j ++) {
for(int k = 0;k < 4;k ++) {
for(int s = 0;s < le[id[k][j]];s ++) {
int x = bu[id[k][j]][s];
if(i & (1<<x))
dp[i][j] = max(dp[i][j],dp[i-(1<<x)][k] + w[x]);
}
}
ans = max(ans,dp[i][j]);
}
}
AIput(ans,'\n');
return 0;
}

【NOI P模拟赛】奶油蛋糕塔(状压 DP)的更多相关文章

  1. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  2. BZOJ 3812 主旋律 (状压DP+容斥) + NOIP模拟赛 巨神兵(obelisk)(状压DP)

    这道题跟另一道题很像,先看看那道题吧 巨神兵(obelisk) 题面 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张nnn个点mmm条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张 ...

  3. 2018.10.05 NOIP模拟 上升序列(状压dp)

    传送门 状压dp好题. 首先需要回忆O(nlogn)O(nlog n)O(nlogn)求lislislis的方法,我们会维护一个单调递增的ddd数组. 可以设计状态f(s1,s2)f(s1,s2)f( ...

  4. 2018.10.01 NOIP模拟 偷书(状压dp)

    传送门 状压dp经典题. 令f[i][j]f[i][j]f[i][j]表示到第i个,第i−k+1i-k+1i−k+1~iii个物品的状态是j时的最大总和. 然后简单维护一下转移就行了. 由于想皮一下果 ...

  5. 旅游(CSUST省赛选拔赛2+状压dp+最短路)

    题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...

  6. [欢乐赛]班服 状压DP

    班服 (shirt.pas/.c/.cpp) 时间限制:1s:内存限制 128MB 题目描述: 要开运动会了,神犇学校的n个班级要选班服,班服共有100种样式,编号1~100.现在每个班都挑出了一些样 ...

  7. [CSP-S模拟测试]:装饰(状压DP)

    题目传送门(内部题114) 输入格式 第一行一个正整数$n$. 接下来一行$n-1$个正整数,第$i$个数为$f_{i+1}$. 接下来一行$n$个数,若第$i$个数为$0$则表示林先森希望$i$号点 ...

  8. war2 洛谷模拟赛day2 t3 状压

    (new )   war2 题解:总体数据而言,我们很容易想到着就是DP啊,我们DP数组,用状态压缩,代表有那些点已经被占领过了,代表上一次我占的是那个.对于每一次状态转移,若当前我们要占领的Port ...

  9. [CSP-S模拟测试]:巨神兵(状压DP)

    题目描述 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张$n$个点$m$条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张图有多少个子图(即选定一个边集)是优美的?答案对$1,000 ...

  10. 【CSP模拟赛】Adore(状压dp 二进制)

    题目描述 小w偶然间见到了一个DAG.这个DAG有m层,第一层只有一个源点,最后一层只有一个汇点,剩下的每一层都有k个节点.现在小w每次可以取反第i(1<i<n-1)层和第i+1层之间的连 ...

随机推荐

  1. HIPPO-4J 1.3.0 正式发布:支持 Dubbo、RibbitMQ、RocketMQ 框架线程池

    文章首发在公众号(龙台的技术笔记),之后同步到个人网站:xiaomage.info Hippo-4J 距离上一个版本 1.2.1 已经过去一个月的时间.在此期间,由 8 位贡献者 提交了 170+ c ...

  2. 聊聊 C# 和 C++ 中的 泛型模板 底层玩法

    最近在看 C++ 的方法和类模板,我就在想 C# 中也是有这个概念的,不过叫法不一样,人家叫模板,我们叫泛型,哈哈,有点意思,这一篇我们来聊聊它们底层是怎么玩的? 一:C++ 中的模板玩法 毕竟 C+ ...

  3. linux安装源码包指定安装目录

    当下载完一个源码包并且解压后 文件夹下会有一个重要的文件configure configure 文件是一个可执行的脚本文件,它将检查目标系统的配置和可用功能,比如一些检查依赖或者启用禁用一些模块,它有 ...

  4. Python爬虫常用:谷歌浏览器驱动——Chromedriver 插件安装教程

    我们在做爬虫的时候经常要使用谷歌浏览器驱动,今天分享下这个Chromedriver 插件的安装方法. 第一步:打开谷歌浏览器打开设置面板 嫌枯燥的小伙伴可以点击此处找管理员小姐姐领取免费资料 第二步: ...

  5. 8.3 如何在Windows电脑安装Java开发环境(JDK)

    下载 来到JDK官方下载界面,找到Java SE 8(简称JDK 8)后面的JDK下载,来到该界面,先同意协议,然后下载对应平台的JDK,我们这里下载Windows x64. 安装 双击安装就行了了, ...

  6. NC16783 [NOIP1998]拼数

    NC16783 [NOIP1998]拼数 题目 题目描述 设有 \(n\) 个正整数(\(n ≤ 20\)),将它们联接成一排,组成一个最大的多位整数. 例如:\(n=3\) 时,\(3\) 个整数 ...

  7. UI自动化测试执行问题总结

    ------------恢复内容开始------------ ![image](https://img2022.cnblogs.com/blog/1510476/202206/1510476-2022 ...

  8. Oracle Database 19c (19.3)

    https://www.oracle.com/database/technologies/oracle19c-windows-downloads.htmlOracle Database 19c (19 ...

  9. idea 分 环境 配置 线上 测试 本地

    在resources 新建application.properties 分开在resources 新建的多个环境的文件 #测试环境 applicaion-test.properties #开发环境 a ...

  10. 如何用 身份证OCR 接口进行快速开发

    最近公司项目有一个身份证文字识别的小需求,想着如果用现成的API就可以大大提高开发效率,在网上的API商店搜索了一番,发现了 APISpace,它里面的身份证OCR非常符合我的开发需求.   身份证O ...