题面


数据范围

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. CNN Training Loop Refactoring Simultaneous Hyperameter Testing

    上例中, 尝试两个不同的值 为此: alt+shift可以有多个光标,再jupyter notebook中. alt+d,alt+shift,ctrl+鼠标左键多点几个,都可以同时选择多个目标,并进行 ...

  2. 论文阅读 dyngraph2vec: Capturing Network Dynamics using Dynamic Graph Representation Learning

    6 dyngraph2vec: Capturing Network Dynamics using Dynamic Graph Representation Learning207 link:https ...

  3. 文件输入输出处理-File

    大佬的理解-><IO流和File> 1.File类 File类是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操作文件.通过调用File类提供的各种方法, ...

  4. 接口偶尔超时,竟又是JVM停顿的锅!

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 继上次我们JVM停顿十几秒的问题解决后,我们系统终于稳定了,再也不会无故重启了! 这是之前的文章:耗时几个月,终于 ...

  5. java中的方法重载(overload)

    什么时候方法重载:当两个方法的功能是相似的,可以考虑使用方法重载.若两个方法根本没有关系,无必要使用方法重载. 什么时候代码会发生方法重载:三个条件:1,在同一个类中.2,方法名相同.3,参数列表相同 ...

  6. Redis基础与性能调优

    Redis是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库.缓存服务或消息服务使用. Redis支持多种数据结构,包括字符串.哈希表.链表.集合.有序集合.位图.Hyperloglogs等. ...

  7. kvm虚拟机在线扩容

    fdisk -l查看当前虚拟机磁盘容量 1. 镜像扩容 先操作镜像,给镜像增加2T容量: 关闭虚拟机back_log,然后再宿主机上给虚拟机扩容 qemu-img info /home/kvm/bac ...

  8. 【Java面试】RDB 和 AOF 的实现原理、优缺点

    Hi,大家好,我是Mic. 一个工作了5年的粉丝私信我,最近面试碰到很多Redis相关的问题. 其中一个面试官问他Redis里面的持久化机制,没有回答得很好. 希望我帮他系统回答一下. 关于Redis ...

  9. 关于 k 进制线性基

    本质还是高斯消元,使其成为上三角矩阵.但是 \(k\) 不一定是质数. 但我们不需要保证已有数字不改变,只要维护的是一个上三角矩阵就行.所以我们可以利用更相减损让其中一个向量的最高位 \(= 0\) ...

  10. 如何等待ajax完成再执行相应操作

    ajax广泛应用于异步请求,对于大多数业务来说,这是十分方便的,但对于一些特殊的业务,ajax的异步性会起到相反的作用. 例如在ajax请求成功后,后续的操作需要依赖ajax执行成功后的相应操作. / ...