BZOJ 4576: [Usaco2016 Open]262144

Description

一个序列,每次可以将两个相同的数合成一个数,价值+1,求最后最大价值 \(n \leqslant 262144\)

Sol

DP.

这道题是 BZOJ 4580: [Usaco2016 Open]248 加强版.

做248的那个区间DP其实很多方案都是0,而且一个区间中只有一个合法的数字.

然后就是 一个区间合成一个数的方案的这个数字是固定的.

\(f[i][j]\) 表示以 \(i\) 结尾是否能合成 \(j\),同时记录一下转移位置,每次向前找前一个指针就可以了.

复杂度 \(O(nm)\)

Code

/**************************************************************
    Problem: 4576
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:1208 ms
    Memory:79368 kb
****************************************************************/

#include <cstdio>
#include <iostream>
using namespace std;

const int N = 263005;
const int M = 60;

int n,ans,a[N];
bool f[N][M];int g[N][M];

inline int in(int x=0){ scanf("%d",&x);return x; }
int main(){
    n=in();
    for(int i=1;i<=n;i++) a[i]=in();
    for(int i=1,p;i<=n;i++){
        p=i-1,f[i][a[i]]=1,g[i][a[i]]=i;
        ans=max(ans,a[i]);
        for(int j=a[i];j<M;j++){
            if(f[p][j]) f[i][j+1]=1,g[i][j+1]=g[p][j],p=g[p][j]-1,ans=max(ans,j+1);
            else break;
        }
    }
//  for(int i=1;i<=n;i++) for(int j=1;j<6;j++) cout<<i<<" "<<j<<" "<<f[i][j]<<" "<<g[i][j]<<endl;
    cout<<ans<<endl;
    return 0;
}

  

时间: 2024-10-13 12:28:21

BZOJ 4576: [Usaco2016 Open]262144的相关文章

BZOJ 4742: [Usaco2016 Dec]Team Building

4742: [Usaco2016 Dec]Team Building Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 21  Solved: 16[Submit][Status][Discuss] Description Every year, Farmer John brings his NN cows to compete for "best in show" at the state fair. His arch -rival, F

bzoj 4412: [Usaco2016 Feb]Circular Barn

4412: [Usaco2016 Feb]Circular Barn Description 有一个N个点的环,相邻两个点距离是1.点顺时针标号为1..N.每一个点有ci头牛,保证∑ci=N.每头牛都可以顺时针走.设一头牛走了d个单位停下了,将耗费d^2的能量.请设计一种牛的走法,使得每一个点上都正好有一头牛,且最小化耗费的能量. Input 第一行一个数N.N <= 100000接下来N行,每行一个数ci. Output 输出一个数表示耗费能量的最小值 Sample Input 10 1 0

bzoj4576 [Usaco2016 Open]262144

题目大意: 给出n个数a[1..n],n<=262144,a[i]<=40,相邻且相同的数可以合并成一个并将值加1,问能获得的最大数是多少 用一个双向链表维护原数列,每个节点记录此节点对应的数值和数的个数,合并相邻且对应数值相同的节点 每次选一个数值最小的点处理,此时两侧的数都更大 若这个点只有一个数则直接删去并断开两侧,此时两侧的数不可能再互相合并 若这个点有偶数个数则数值+1,个数/2,检测能否和两侧合并 若这个点有奇数个数,两侧的数也不可能再互相合并了,因此将这个点分裂成两个互不相连的点

bzoj 4506: [Usaco2016 Jan]Fort Moo

4506: [Usaco2016 Jan]Fort Moo Description Bessie is building a fort with her friend Elsie. Like any good fort, this one needs to start with a sturdy frame. Bessie wants to build a frame in the shape of a one-meter-wide rectangular outline, atop which

Bzoj 4582 [Usaco2016 Open] Diamond Collector 题解

4582: [Usaco2016 Open]Diamond Collector Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 204  Solved: 136[Submit][Status][Discuss] Description Bessie the cow, always a fan of shiny objects, has taken up a hobby of mining diamonds in her spare time! Sh

BZOJ 4579: [Usaco2016 Open]Closing the Farm

Description 依次删去一个点和它的边,问当前图是否连通. Sol 并查集. 倒着做就可以了. 每次将一个点及其的边加入,如果当前集合个数大于 1,那么就不连通. Code /************************************************************** Problem: 4579 User: BeiYu Language: C++ Result: Accepted Time:2196 ms Memory:10328 kb *********

BZOJ 4581: [Usaco2016 Open]Field Reduction

Description 有 \(n\) 个点,删掉三个点后,求最小能围住的面积. Sol 搜索. 找出 左边/右边/上边/下边 的几个点枚举就可以了. 我找了 12 个点,统计一下坐标的个数,然后找到最大最小坐标. PS:md.Cena 好像对 STL 不太友好啊,用 map 居然T了???exm??? 昨天用 map 离散化就T的飞起.md..mama我再也不用 map 离散化了...以后用lower_bound()好了... 一开始写了个DFS来枚举...发现不是很好...又删掉变成三维循环

BZOJ 4580: [Usaco2016 Open]248

Description 一个序列,每次可以把相邻的两个数合为一个,价值+1,求最后的最大价值. Sol 区间DP. \(f[i][j]\) 表示 \(i-j\) 中合成一个数字为多少,转移就是枚举断点,断点两边的价值一样,就合并. 复杂度 \(O(n^3)\) Code /************************************************************** Problem: 4580 User: BeiYu Language: C++ Result: Ac

BZOJ 4582: [Usaco2016 Open]Diamond Collector

Descrirption 给你一个长度为 \(n\) 的序列,求将它分成两个序列后最多个数,每个序列最大值最小值不能超过 \(k\) Sol 二分+DP. 排一下序,找出以这个点结尾和开始的位置. 这个玩意可以二分也可以用单调队列,随便搞啊... 然后统计答案就是枚举第二个序列的起点,然后往后扫的时候统计一下,第一个序列的最大长度就可以了. Code /************************************************************** Problem: