• Codeforces-834D The Bakery 线段树优化DP


    给n个数,让你分成k个子段,让每个子段中不同数字个数的和最大

    dp[i][j]:前i个元素分成j段的最大和

    考虑第j段,他的开头为k,那么dp[i][j]=max{dp[k][j-1]+sum[k+1][i] | 0<=k<=i-1 }

    节点i维护dp[k]+sum(k+1,i),0<=k<=i-1,k是上一段的结尾,即第j层外循环决定了第j个区间是[k+1,i]

    #include<bits/stdc++.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #include<iostream>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<iomanip>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define FOR(a) for(int i=1;i<=a;i++)
    const int inf=0x3f3f3f3f;
    const int maxn=3e5+9; 
    const int mod=1e9+7;
    
    int n,k;
    
    int dp[maxn];
    
    struct NODE{
    	int maxx,lazy;
    }ST[maxn<<2];
    
    void pushup(int rt){ST[rt].maxx=max(ST[rt<<1].maxx,ST[rt<<1|1].maxx);}
    void build(int l,int r,int rt){
    	ST[rt].lazy=0;
    	if(l==r){ST[rt].maxx=dp[l];return;}
    	int m=l+r>>1;build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt);
    }
    void pushdown(int rt){
    	if(ST[rt].lazy){
    		ST[rt<<1].lazy+=ST[rt].lazy;ST[rt<<1].maxx+=ST[rt].lazy;
    		ST[rt<<1|1].lazy+=ST[rt].lazy;ST[rt<<1|1].maxx+=ST[rt].lazy;
    		ST[rt].lazy=0;
    	}
    }
    void update(int a,int b,int c,int l,int r,int rt){
    	if(a<=l&&b>=r){ST[rt].maxx+=c;ST[rt].lazy+=c;return;}
    	pushdown(rt);
    	int m=l+r>>1;
    	if(a<=m)update(a,b,c,l,m,rt<<1);
    	if(b>m)update(a,b,c,m+1,r,rt<<1|1);pushup(rt);
    }
    int query(int a,int b,int l,int r,int rt){
    	if(a<=l&&b>=r)return ST[rt].maxx;
    	int m=l+r>>1,ans=0;
    	if(a<=m)ans=query(a,b,l,m,rt<<1);
    	if(b>m)ans=max(ans,query(a,b,m+1,r,rt<<1|1));
    	return ans;
    }
    
    int arr[maxn],pre[maxn],lst[maxn];
    int main(){
    	scanf("%d%d",&n,&k);
    	FOR(n){
    		scanf("%d",&arr[i]);
    		pre[i]=lst[arr[i]],lst[arr[i]]=i;
    	}
    	for(int j=1;j<=k;j++){	
    		build(0,n,1);
    		for(int i=1;i<=n;i++){	//枚举前i个元素
    			update(pre[i],i-1,1,0,n,1);
    			dp[i]=query(0,i-1,0,n,1);
    		}
    	}
    	printf("%d
    ",dp[n]);
    }

    线段树DP。。之前多校也有一题,体感没这个难

    仔细想想也是,DP的转移就是取max,因此用线段树维护DP值也没什么奇怪的

    感觉果然好难,这就是目前自己的天花板了吧。。。。要加油啊!

  • 相关阅读:
    JS 改变鼠标样式
    jquery 实践操作:iframe 相关操作
    jquery 实践操作:div 动态嵌套(追加) div
    jquery 实践操作:div 动态嵌套页面
    jquery 实践操作:attr()方法
    jquery 实践操作:load()方法
    nodeJS(2)深了解: nodeJS 项目架构详解(app.js + Express + Http)
    photoshop 安装
    Github 使用记录
    PhpStorm 10.0.1安装(win7-64位)
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611285.html
Copyright © 2020-2023  润新知