首页 > 其他分享 >CodeForces - 833B The Bakery

CodeForces - 833B The Bakery

时间:2022-11-21 19:44:09浏览次数:54  
标签:833B lazy val int tr CodeForces Bakery now dp

看题解时全程:wow

题意:给出n个数,将其按顺序分为k组,令每组的价值为该组不同的数的个数。求一种分法,使得所有组价值和最大。

解:设dp[i][j]为将前 j 个数分为 i 组时的最大价值,显然有dp[i][j]=max(dp[i-1][k]+sum[k+1...j]),sum[k+1...j]为[k+1...j]中不同数的个数。然后优化求解过程,先解决sum怎么求。设原数组为a[i],令c[i]为区间[i, n]内不同数的个数,pre[i]为a[i]最后一次出现的位置,那么对于每一个i,c[pre[i]+1...i]+1,最终结果即为数组定义。意思是在pre[i]+1到i之间没有出现过a[i],那么它可以对答案贡献1,并且这样做不会有重复加的情况出现。

以样例3为例:

a:   7 7 8 7 7 8 1 7

pre+1:1 2 1 3 5 4 1 6

index:   1 2 3 4 5 6 7 8

c:   3 3 3 3 3 3 2 1

然后再来看这道题。通常我们先枚举i,再枚举j,也就是一个数一个数往里加。每添加一个数j,就可以获得所有的[k+1...j],很快乐,直接在dp[i-1]上加然后求最大值即可。区间加和求最大值的数据结构显然用线段树。注意给dp[i][k]加上c[k+1]的值,不是c[k]。

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxx 35005
#define maxn 25
#define maxm 205
#define ll long long
#define inf 1000000009
#define mod 2520
int a[maxx]={0};
int dp[55][maxx]={0};
int pre[maxx]={0},pos[maxx]={0};
struct node{
    int val,lazy;
}tr[maxx*4];
void pushup(int now){
    tr[now].val=max(tr[now*2].val,tr[now*2+1].val);
}
void pushdown(int now){
    if(!tr[now].lazy){
        return;
    }
    tr[now*2].lazy+=tr[now].lazy;
    tr[now*2+1].lazy+=tr[now].lazy;
    tr[now*2].val+=tr[now].lazy;
    tr[now*2+1].val+=tr[now].lazy;
    tr[now].lazy=0;
}
int ii;
void build(int now,int l,int r){
    if(l==r){
        tr[now].val=dp[ii][l-1];
        tr[now].lazy=0;
        return ;
    }
    tr[now].lazy=0;
    int mid=(l+r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    pushup(now);
}
void add(int now,int l,int r,int s,int e){
    if(s<=l&&r<=e){
        tr[now].val+=1;
        tr[now].lazy+=1;
        return;
    }
    pushdown(now);
    int mid=(l+r)/2;
    if(s<=mid) add(now*2,l,mid,s,e);
    if(mid<e) add(now*2+1,mid+1,r,s,e);
    pushup(now);
}
int query(int now,int l,int r,int s,int e){
    if(s<=l&&r<=e){
        return tr[now].val;
    }
    pushdown(now);
    int mid=(l+r)/2;
    int res=0;
    if(s<=mid) res=max(res, query(now*2,l,mid,s,e));
    if(mid<e) res=max(res, query(now*2+1,mid+1,r,s,e));
    return res;
}

signed main() {
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        pre[i]=pos[a[i]]+1;
        pos[a[i]]=i;
    }
    for(int i=1;i<=k;i++){
        ii=i-1;
        build(1,1,n);
        for(int j=1;j<=n;j++){
            add(1,1,n,pre[j],j);
            dp[i][j]= query(1,1,n,1,j);
        }
    }
    printf("%d\n",dp[k][n]);
    return 0;
}
//dp[i][j] the first j th num, distribute into i blocks
//dp[i][j]=max(dp[i-1][k]+sum[k+1...j])
View Code

 

标签:833B,lazy,val,int,tr,CodeForces,Bakery,now,dp
From: https://www.cnblogs.com/capterlliar/p/16912969.html

相关文章

  • Codeforces Round #833 (Div. 2)
    C题挂\(4\)发赛后再挂\(4\)发AB耻辱跑路。A.TheUltimateSquare有\(n\)个木块,第\(i\)块长\(\lceil\frac{i}{2}\rceil\)宽\(1\),则用这些木块拼成的最......
  • Codeforces 1740 F Conditional Mix 题解
    题目链接对于任意一个multiset,我们都把它的元素从大到小排序来观察。发现一个multiset合法有个必要条件:对于每个i,multiset中最大的i个元素之和不能超过\(lim_i\),如果令\(c......
  • Codeforces 704 B Antman 题解 (dp,贪心,结论)
    题目链接这题两种不同做法,普通的\(O(n^2)\)和奇怪的\(O(nlogn)\)。如果用\(O(nlogn)\)的话可以加强到1e6。做法1时间复杂度\(O(n^2)\)先把最终的排列随便画一个出来观......
  • CodeForces - 797F Mice and Hole
    题意:有n只老鼠,m个洞。n只老鼠的坐标分别为x[i],m个洞坐标分别为p[i],能装c[i]只老鼠。现在老鼠要往洞里跑,求所有老鼠跑的最短路线之和。解:一开始准备拿老鼠转移,然后复杂度爆......
  • Codeforces Round #834 (Div. 3) A-G
    比赛链接A题目知识点:模拟。确定开头字母,然后循环比较即可。时间复杂度\(O(n)\)空间复杂度\(O(n)\)题解#include<bits/stdc++.h>#definelllonglongusingn......
  • Codeforces Round #834 (Div. 3) G
    G.RestorethePermutation对于一个序列要是我们从数小a[i]的开始每次给这个a[i]选一个最接近她的一个小的显然我们这样是最合法的但是怎么保证字典序最小呢显然我......
  • 题解 Codeforces Round #834 (Div. 3) ABCDEF
    A.Yes-Yes?problem判断给定的字符串是否为无穷个YesYesYes拼接组成的字符串的连续子串。\(|S|\leq50\)。solution暴力。具体地,判断\(S,Ye+S,Y+S\)是否有一个是......
  • Codeforces Round #834 (Div. 3)
    ABC略。D.MakeItRound问题可以看成凑出尽可能多的\(10\)作为因子。注意到\(10\)的因子只有\(1,2,5,10\)。首先,\(n\)自己已经凑出来的\(10\)没必要拆开,并......
  • Codeforces Round #829 A+B+C+D 题解
    A.TheUltimateSquare题意询问\(T\)次,给定\(n\)块木板,第\(i\)块为\(1\times\lceil\fraci2\rceil\)大小,求能拼出的最大正方形边长数据范围:\(1\len\le10^9,1......
  • CodeForces - 15D Map
    题意:要在一片n*m的地上盖一个a*b的房子。这片地参差不齐,如果选定一个a*b的区域盖房子的话,需要把这片地铲地和最低点一样平,消耗的代价为铲掉高度之和。按代价大小求所有不重......