OwO http://codeforces.com/contest/833/problem/B

  首先读入的时候把数据读入到2 ~ n+1的位置(因为线段树处理不到0,所以后移了一格)

  dp[i][j]代表处理到第i个位置为止,分j段能得到的最大值

  lst[i]记录第与第i个蛋糕一样的蛋糕出现的上一个位置

  则,显然dp[i][j]=min(dp[i-t][j-1]+(从i-t+1到i位置的不同种类的蛋糕个数))

  记对每一段的值有贡献的点为同一段每种类型蛋糕最左边的点(比如其中一段AAFBCCDBAB,那么对这一段有贡献的B为F后面的那个B,因为他最先出现)

  那么可以从小到大枚举k

  每一次枚举的时候根据k-1时的dp值建一个线段树,从左往右遍历蛋糕数组,扫到第i个蛋糕的时候,线段树上第t个点表示的是上一段的右端点取t时(即这一段起点取t+1)dp[i][k]的取值,那么显然这是一个区间最大值得线段树

  维护的话,扫到第i个蛋糕的时候,线段树上(lst[i],i-1)区间的值+1,因为第k-1个区间的右端点取t取(lst[i],i-1)上的点时(即第k个区间为(t+1,i),包括了第i个蛋糕,而且第i个蛋糕为该区间第一个该种蛋糕),cake[i]种类对第k个区间有贡献

  查询的话,扫到第i个蛋糕的时候,查询第k-1段右节点可以选的那一段的就可以了

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath> using namespace std; const int M=5e4; int dp[M][60],nowk;
int tree[M*3],tag[M*3]; void build(int rt,int li,int ri)
{
tag[rt]=0;
if(li==ri)
{
tree[rt]=dp[li][nowk];
return ;
}
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
build(lc,li,mid);
build(rc,mid+1,ri);
tree[rt]=max(tree[lc],tree[rc]);
} void pushdown(int rt,int li,int ri)
{
if(li==ri)
{
tag[rt]=0;
return ;
}
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
tree[lc]+=tag[rt];
tree[rc]+=tag[rt];
tag[lc]+=tag[rt];
tag[rc]+=tag[rt];
tag[rt]=0;
} void update(int rt,int li,int ri,int lq,int rq,int val) //add
{
if(lq<=li && ri<=rq)
{
tag[rt]+=val;
tree[rt]+=val;
return ;
}
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
if(tag[rt])
pushdown(rt,li,ri);
if(mid>=lq)
update(lc,li,mid,lq,rq,val);
if(mid+1<=rq)
update(rc,mid+1,ri,lq,rq,val);
tree[rt]=max(tree[lc],tree[rc]);
} int query(int rt,int li,int ri,int lq,int rq) //get max
{
int ret=-1e9-7;
if(lq<=li && ri<=rq)
return tree[rt];
int mid=(li+ri)>>1,lc=(rt<<1),rc=(rt<<1)+1;
if(tag[rt])
pushdown(rt,li,ri);
if(mid>=lq)
ret=max(ret,query(lc,li,mid,lq,rq));
if(mid+1<=rq)
ret=max(ret,query(rc,mid+1,ri,lq,rq));
return ret;
} int n,k;
int cake[M];
int lst[M],tmp[M];
int ans; void init()
{
int i,j;
for(i=1;i<=n+1;i++)
tmp[i]=1;
for(i=2;i<=n+1;i++)
{
lst[i]=tmp[cake[i]];
tmp[cake[i]]=i;
}
ans=0;
memset(dp,0,sizeof(dp));
} int main()
{
int i,j,tmp;
scanf("%d%d",&n,&k);
for(i=2;i<=n+1;i++)
scanf("%d",&cake[i]);
init();
n++;
for(i=1;i<=k;i++)
{
nowk=i-1;
build(1,1,n);
for(j=i+1;j<=n;j++)
{
update(1,1,n,lst[j],j-1,1);
tmp=query(1,1,n,i,j-1);
// cout<<tmp<<endl;
dp[j][i]=max(dp[j][i],tmp);
}
}
ans=dp[n][k];
cout<<ans<<endl;
return 0;
}

  

Codeforces 833B / B34D The Bakery的更多相关文章

  1. codeforces 834 D. The Bakery

    codeforces 834 D. The Bakery(dp + 线段树优化) 题意: 给一个长度为n的序列分成k段,每段的值为这一段不同数字的个数,最大化划分k端的值 $n <= 35000 ...

  2. Codeforces 833B The Bakery dp线段树

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

  3. Codeforces 833B The Bakery(主席树 + 决策单调性优化DP)

    题目链接 The Bakery 题目大意:目标是把$n$个数分成$k$组,每个组的值为这个组内不同的数的个数,求$k$个组的值的和的最大值. 题目分析: 这道题我的解法可能和大众解法不太一样……我用主 ...

  4. CodeForces - 833B The Bakery

    题解: 线段树经典应用 首先暴力$f[i][j]$表示考虑前i位分成j段的最大值 转移$f[k][j-1]+cost(k+1,i)$枚举k转移 不同数的经典套路就是从它到它前驱这一段 于是维护每个数前 ...

  5. Codeforces.833B.The Bakery(线段树 DP)

    题目链接 \(Description\) 有n个数,将其分为k段,每段的值为这一段的总共数字种类,问最大总值是多少 \(Solution\) DP,用\(f[i][j]\)表示当前在i 分成了j份(第 ...

  6. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

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

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

  8. 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 ...

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

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

随机推荐

  1. shell 字符

    Shell 中的符号: 在shell中有很多符号代表了一些意思,重点说说 键盘上的符号在shell中的意义. 通配符: ~ 匹配家目录 ?  匹配单个字符.( ?之匹配单一的一个字符.x11 这种的就 ...

  2. 【LOJ】#3094. 「BJOI2019」删数

    LOJ#3094. 「BJOI2019」删数 之前做atcoder做到过这个结论结果我忘了... em,就是\([1,n]\)之间每个数\(i\),然后\([i - cnt[i] + 1,i]\)可以 ...

  3. 什么是NameNode和DataNode?他们是如何协同工作的?

    [学习笔记] 什么是NameNode和DataNode?他们是如何协同工作的? 马克-to-win @ 马克java社区:一个HDFS集群包含一个NameNode和若干的DataNode(start- ...

  4. 虚拟机(Vmware)安装ubuntu18.04和配置调整(二)

    二.配置修改 1.修改语言环境(settings->Region & Language) 选中中文简体(Chinese(simplified)),点击Apply 中文简体语言安装完成后, ...

  5. curl post请求封装

    /* POST /servlet/ICBCCMPAPIReqServlet?userID=jyi.y.1001&PackageID=201807311347539185&SendTim ...

  6. 快速开启关闭mysql,批命令方便!

    很多python开发人员和我一样,都会在自己的电脑上配置一个python开发的环境,便于开发和学习使用,比如我现在电脑上使用的就是mysql数据库,而我的电脑配置又比较低,电脑运行起来会出现卡慢的情况 ...

  7. HTTP、HTTPS、WebSocket

    一 .HTTP 1.1 HTTP发展史 1.1.1 什么是HTTP 超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所 ...

  8. Jmeter之Dummy Sampler

    Dummy Sampler(Dummy取样器) Dummy Sampler就像是一个模拟器,需要自己填入请求和响应的信息.(原理类似mock服务) 在没有服务的情况下,测试人员依据Dummy Samp ...

  9. Winfrom 定时锁屏

    #region 锁屏 public struct LASTINPUTINFO { [MarshalAs(UnmanagedType.U4)] public int cbSize; [MarshalAs ...

  10. 自定义springboot-starter

    参考: https://juejin.im/entry/5b447cbbe51d45199566f752 https://www.baeldung.com/spring-boot-custom-sta ...