题面


数据范围

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. Makefile基础语法

    Makefile的作用 如果没有Makefile,每次修改源代码后,如果要重新编译代码,都要输入编译命令,当源代码很多时,效率很底下. 基本格式 target: componsnts TAB rule ...

  2. 字符串的操作、 Math类

    字符串的操作 我们先来定义一个字符串,如果来进行过去长度,获取内容. 我们来写一个小测试! public static void main(String[] args) { String aa = & ...

  3. Camunda如何适配国产数据库达梦

    前言 camunda流程引擎官方支持的数据库有:MySQL .MariaDB .Oracle .DB2 .PostgreSQL .SQL Server.H2.对于其他类型的数据库如何支持,尤其是国产数 ...

  4. camunda开源版与商业版的差异

    Camunda流程引擎分社区版和企业版,社区版实际上是开源版,是Apache2.0协议,企业版实际上是商业收费版本,需要购买授权才能使用,那么社区版和企业版的差异有哪些呢,社区版本是否能满足我们日常的 ...

  5. 2022年Web前端开发流程和学习路线(详尽版)

    前言 前端侧重于人机交互和用户体验,后端侧重于业务逻辑和大规模数据处理.理论上,面向用户的产品里,所有问题(包括产品.设计.后端.甚至看不见的问题)的表现形式,都会暴露在前端,而只有部分问题(数据问题 ...

  6. docker 操作 记录

    docker ps  #查看当前docker容器 docker exec -it  容器名称 sh  进入docker容器 docker stop 停止docker容器

  7. VMware Workstation 虚拟机安装教程

    一.介绍篇 VMware Workstation 16 Pro是VMware(威睿公司)于2021年最新发布的一代虚拟机软件,软件的中文名是"VMware 工作站 16 专业版". ...

  8. Typora图片与阿里云OSS图床的结合之旅

    图床? 专门用于存放图片,并允许用户通过独一的外链进行特定图片资源的访问 为什么是阿里云OSS(Object Storage Service) 码云开源需要审核,已经不能作为免费的图床使用(2022年 ...

  9. SAP 实例 4 CFW

    *&---------------------------------------------------------------------* *& Report demo_cfw ...

  10. KVM虚拟机安装及桥接网络配置

    1.查看CPU是否支持intel或AMD的虚拟技术 cat /proc/cpuinfo | grep -E "vmx|svm" --color --vmx intel的CPU sv ...