Portal

Description

给出一个\(n(n\leq35000)\)个数的数列\(\{a_i\}\)和\(m(m\leq50)\)。将原数列划分成\(m\)个连续的部分,每个部分的权值等于其中不同的数的个数。求所有划分方案中,所有部分权值和中的最大值。

Solution

线段树优化DP。

记录\(f[k][i]\)表示将前\(i\)个数划分为\(k\)段的最大权值和,\(w(i,j)\)表示\([L,R]\)的权值,那么容易列出转移方程:

\[ f[k][i]=max\{f[k-1][j]+w(j+1,i)\} \quad (0\leq j \leq i-1)$$ 复杂度为$O(n^2m)$。
考虑一下如何简化$w$。记录$a_x$上一次出现的位置为$pre_x$,则$a_x$为$pre_x+1\leq i \leq x$的$w(i,x)$提供了$1$的贡献。那么我们如果想从$w(i,x-1)$转移到$w(i,x)$,只需对区间$[pre_x+1,x]$加$1$即可。
那么我们要做的就是维护$f[k-1][j]+w(j+1,i)$的区间最值,用线段树即可。第二维由$i$变为$i+1$时,对线段树进行一次区间加即可。
> 时间复杂度$O(nk\cdot logn)$。

##Code
```cpp
//The Bakery
#include <cstdio>
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
inline int max(int x,int y) {return x>y?x:y;}
const int N=4e4;
int n,m,a[N];
int pre[N],pre1[N];
#define Ls (p<<1)
#define Rs (p<<1|1)
const int N1=N<<2;
int rt,val[N1]; int add[N1];
void update(int p) {val[p]=max(val[Ls],val[Rs]);}
void addV(int p,int v) {add[p]+=v,val[p]+=v;}
void pushdw(int p) {if(add[p]) addV(Ls,add[p]),addV(Rs,add[p]),add[p]=0;}
int optL,optR;
void ins(int p,int L0,int R0,int v,int type)
{
if(optL<=L0&&R0<=optR)
{
if(type==1) addV(p,v);
else val[p]=v;
return;
}
pushdw(p);
int mid=L0+R0>>1;
if(optL<=mid) ins(Ls,L0,mid,v,type);
if(mid<optR) ins(Rs,mid+1,R0,v,type);
update(p);
}
int query(int p,int L0,int R0)
{
if(optL<=L0&&R0<=optR) return val[p];
pushdw(p);
int mid=L0+R0>>1; int r=0;
if(optL<=mid) r=max(r,query(Ls,L0,mid));
if(mid<optR) r=max(r,query(Rs,mid+1,R0));
return r;
}
int f[N];
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
pre[i]=pre1[a[i]],pre1[a[i]]=i;
}
rt=1;
for(int k=1;k<=m;k++)
{
for(int i=k;i<=n;i++)
{
optL=pre[i],optR=i-1,ins(rt,0,n,1,1);
optL=0,optR=i-1,f[i]=query(rt,0,n);
}
if(k==m) break;
for(int i=0;i<=n;i++) optL=optR=i,ins(rt,0,n,f[i],2);
}
printf("%d\n",f[n]);
return 0;
}
```\]

Codeforces834D - The Bakery的更多相关文章

  1. Codeforeces 707B Bakery(BFS)

    B. Bakery time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  2. Codeforces Round #368 (Div. 2) B. Bakery (模拟)

    Bakery 题目链接: http://codeforces.com/contest/707/problem/B Description Masha wants to open her own bak ...

  3. 信号量和PV操作写出Bakery算法的同步程序

    面包店烹制面包及蛋糕,由n个销售员卖出.当有顾客进店购买面包或蛋糕时,应先在取号机上取号,然后等待叫号,若有销售员空闲时便叫下一号,试用信号量和PV操作写出Bakery算法的同步程序. 设计要求 1) ...

  4. Codeforces 834D The Bakery【dp+线段树维护+lazy】

    D. The Bakery time limit per test:2.5 seconds memory limit per test:256 megabytes input:standard inp ...

  5. Codeforces 834D The Bakery - 动态规划 - 线段树

    Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredient ...

  6. Codeforces Round #426 (Div. 1) B The Bakery (线段树+dp)

    B. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  7. Codeforces Round #368 (Div. 2) B. Bakery 水题

    B. Bakery 题目连接: http://www.codeforces.com/contest/707/problem/B Description Masha wants to open her ...

  8. Codeforces 834D - The Bakery(dp+线段树)

    834D - The Bakery 思路:dp[i][j]表示到第j个数为止分成i段的最大总和值. dp[i][j]=max{dp[i-1][x]+c(x+1,j)(i-1≤x≤j-1)},c(x+1 ...

  9. CF833B The Bakery 线段树,DP

    CF833B The Bakery LG传送门 线段树优化DP. 其实这是很久以前就应该做了的一道题,由于颓废一直咕在那里,其实还是挺不错的一道题. 先考虑\(O(n^2k)\)做法:设\(f[i][ ...

随机推荐

  1. 交叉熵cross entropy和相对熵(kl散度)

    交叉熵可在神经网络(机器学习)中作为损失函数,p表示真实标记的分布,q则为训练后的模型的预测标记分布,交叉熵损失函数可以衡量真实分布p与当前训练得到的概率分布q有多么大的差异. 相对熵(relativ ...

  2. mac 使用homebrew 安装mysql

    1. 安装homebrew ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" brew update ...

  3. javascript原生方法集锦

    1.sort方法sort()方法使数组中的元素按照一定的顺序排列. 语法: arrayObject.sort(方法函数) 参数说明: 1.如果不指定<方法函数>,则按unicode码顺序排 ...

  4. 基于matlab的蓝色车牌定位与识别---识别

    接着昨天的工作,把最后一部分识别讲完. 关于字符识别这块,一种最省事的办法是匹配识别,将所得的字符和自己的标准字符库相减,计算所得结果,值最小的即为识别的结果.不过这种方法是在所得字符较为标准的情况, ...

  5. 模拟发送http请求的工具推荐

    做网站开发时,经常需要发送请求来测试自己的代码是否OK,这时候模拟发送http请求的工具就起到了很大的作用.特别是需要在请求带header时就更加的有必要使用工具.下面推荐的工具有的是基于系统开发的程 ...

  6. mysql按指定顺序排序

    select id,name from htms_center_freight_users where id in(114,112,91,223,134) order by find_in_set(i ...

  7. OpenCV中图像的读取,显示与保存

      图像的读取,显示与保存 相关函数:cv2.imread().cv2.imshow().cv2.imwrite() 1.读入图像: 用cv2.imread()函数来读取图像,cv2.imread(路 ...

  8. poj 1862 2*根号(n1*n2)问题 贪心算法

    题意: 有n个数,要把其中2个数进行2*根号(n1*n2)操作,求剩下最小的那个数是多少? 哭诉:看题目根本没看出来要让我做这个操作. 思路: 每次把最大的,次大的拿出来进行操作 用"优先队 ...

  9. poj 1017 装箱子问题 贪心算法

    题意:有1*1到6*6的的东西,需要用6*6的箱子将它们装起来.问:至少需要多少个6*6箱子 思路: 一个瓶子怎么装东西最多?先装石头,在装沙子,然后装水. 同样放在本题就是先装6*6然后5*5... ...

  10. Android library projects cannot be launched解决方法

    着了一个例子项目,总是报标题说的错误. 解决方法如下: 红圈的地方,勾掉. 貌似如果你这个项目是作为一个被引用的project的话, 要勾上这个.单独作为一个app的话,不能勾选这个. --不懂,瞎写 ...