zoukankan      html  css  js  c++  java
  • 【动态规划】【线段树】 Codeforces Round #426 (Div. 1) B. The Bakery

    给你一个序列,让你划分成K段,每段的价值是其内部权值的种类数,让你最大化所有段的价值之和。

    裸dp

    f(i,j)=max{f(k,j-1)+w(k+1,i)}(0<=k<i)

    先枚举j,然后枚举i的时候,用线段树进行优化,对a(i)上一次出现的位置到i之间的f(k,j-1)的答案进行+1,然后求个i的前缀max。

    要注意线段树区间加的时候其实要包含上0。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define lson rt<<1,l,m
    #define rson rt<<1|1,m+1,r
    int n,m,a[35010],f[35010][60];
    int maxv[35010<<2];
    int delta[35010<<2];
    void pushdown(int rt)//将rt结点的懒惰标记下传 
    {
    	if(delta[rt])
    	  {
    		delta[rt<<1]+=delta[rt];//标记下传到左结点 
    		delta[rt<<1|1]+=delta[rt];//标记下传到右结点 
    		maxv[rt<<1]+=delta[rt];
    		maxv[rt<<1|1]+=delta[rt];
    		delta[rt]=0;
    	  }
    }
    void update(int ql,int qr,int v,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr)
    	  {
    		delta[rt]+=v;//更新当前结点的标记值 
    		maxv[rt]+=v;
    		return ;
    	  }
    	pushdown(rt);//将该节点的标记下传到孩子们 
    	int m=(l+r)>>1;
    	if(ql<=m)
    	  update(ql,qr,v,lson);
    	if(m<qr)
    	  update(ql,qr,v,rson);
    	maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
    }
    int query(int ql,int qr,int rt,int l,int r)
    {
    	if(ql<=l&&r<=qr)
    	  return maxv[rt];
    	pushdown(rt);//将该节点的标记下传到孩子们 
    	int m=(l+r)>>1;
    	int res=-2147483647;
    	if(ql<=m)
    	  res=max(res,query(ql,qr,lson));
    	if(m<qr)
    	  res=max(res,query(ql,qr,rson));
    	return res;
    }
    int now[35010],last[35010];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i]);
    	}
    	for(int i=1;i<=n;++i){
    		last[i]=now[a[i]];
    		now[a[i]]=i;
    	}
    	for(int j=1;j<=m;++j){
    		if(j!=1){
    			memset(maxv,0,sizeof(maxv));
    			memset(delta,0,sizeof(delta));
    			for(int i=j-1;i<=n;++i){
    				update(i,i,f[i][j-1],1,0,n);
    			}
    		}
    		update(max(last[j],j-1),j-1,1,1,0,n);
    		f[j][j]=j;
    		for(int i=j+1;i<=n;++i){
    			update(max(last[i],j-1),i-1,1,1,0,n);
    			f[i][j]=query(j-1,i-1,1,0,n);
    		}
    	}
    	printf("%d
    ",f[n][m]);
    	return 0;
    }
  • 相关阅读:
    课程作业四 生成随机数并求和,大数运算
    课程作业三 string,char操作
    课程作业二 类内静态内容(代码块,静态变量),构造函数,非静态代码块执行顺序
    十一作业 java数值范围方面训练
    课程作业一 将字符串型数组里的数字相加
    NABCD需求分析
    人月神话阅读笔记01
    软件工程第五周总结
    清明第三天
    清明第二天安排
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7261165.html
Copyright © 2011-2022 走看看