code force 833B The Bakery
2017-08-02 17:27
204 查看
题意可以总结为把一堆数分割成k份,每份的权值定义为里面不同数个数,要让总的权值最大。
这种类型的题目第一反应要想到用dp,有两个参数,第一维是k份,第二维是物品个数。dp[i][j]。
然后分析转移。
对于某个物品,他要产生贡献,则必定是到上一次出现这个4号之前的位置都能加一。而这个位置而言指的是如果在这个位置断开,新开一个区间来装4这个物品就能总的权值加1,比如说在这个物品的前一个4还要前的位置断开,这个区间就有两个4了,并不能让总的权值加1。
理解完状态的转移之后,可以用n的平方方法来往前找dp[i][j]=MAX(dp[i-1][0~prej-1],dp[i-1][prej~j-1]+1)。这就像一个前一个dp中来一个区间更新,然后再找查询0~j-1中的dp最大值进行转移。也就是很像线段树的操作,所以可以用线段树进行维护这个dp转移。
这种类型的题目第一反应要想到用dp,有两个参数,第一维是k份,第二维是物品个数。dp[i][j]。
然后分析转移。
对于某个物品,他要产生贡献,则必定是到上一次出现这个4号之前的位置都能加一。而这个位置而言指的是如果在这个位置断开,新开一个区间来装4这个物品就能总的权值加1,比如说在这个物品的前一个4还要前的位置断开,这个区间就有两个4了,并不能让总的权值加1。
理解完状态的转移之后,可以用n的平方方法来往前找dp[i][j]=MAX(dp[i-1][0~prej-1],dp[i-1][prej~j-1]+1)。这就像一个前一个dp中来一个区间更新,然后再找查询0~j-1中的dp最大值进行转移。也就是很像线段树的操作,所以可以用线段树进行维护这个dp转移。
#include<bits/stdc++.h> using namespace std; const int MAXN = 35000+10; int n,k; int cake[MAXN]; class Seg//线段树查询区间最大值 { int maxv[MAXN*4]; int add[MAXN*4]; void pushdown(int rt) { if(add[rt]) { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; maxv[rt<<1]+=add[rt]; maxv[rt<<1|1]+=add[rt]; add[rt]=0; } } void pushup(int rt) { maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]); } public: void build(int rt,int l,int r) { add[rt]=0; if(l==r) { maxv[rt]=add[rt]=0; pushup(rt); return; } int m=l+r>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); pushup(rt); } void updata(int rt,int l,int r,int left,int right,int value) { if(l>=left&&r<=right) { maxv[rt]+=value; add[rt]+=value; return; } pushdown(rt); int m=l+r>>1; if(left<=m) updata(rt<<1,l,m,left,right,value); if(right>=m+1) updata(rt<<1|1,m+1,r,left,right,value); pushup(rt); } int query(int rt,int l,int r,int left,int right) { if(left<=l&&right>=r) return maxv[rt]; if(left>r||right<l) return 0; pushdown(rt); int m=l+r>>1; return max(query(rt<<1,l,m,left,right),query(rt<<1|1,m+1,r,left,right)); } }seg[55]; int last[MAXN]; int pos[MAXN]; int main() { if (fopen("in.txt", "r") != NULL) { freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); } cin>>n>>k; for(int i=1;i<=n;i++) { scanf("%d",cake+i); last[i]=pos[cake[i]];//这个颜色上一次出现的位置 pos[cake[i]]=i;//更新位置 } seg[0].build(1,0,n); for(int i=1;i<=k;i++) { seg[i].build(1,0,n); for(int j=1;j<=n;j++) { seg[i-1].updata(1,0,n,last[j],j-1,1); int dp=seg[i-1].query(1,0,n,0,j-1); seg[i].updata(1,0,n,j,j,dp); } } cout<<seg[k].query(1,0,n,0,n); return 0; }
相关文章推荐
- codeforce 2A-2B
- codeforce 148D. Bag of mice[概率dp]
- codeforce之 Bear and Colors
- codeforce D. Password
- codeforce 379(div.2)
- codeforce 675C Money Transfers (思维)
- CodeForce Round 219 Div2 E Watching Fireworks is Fun 单调队列DP
- codeforce #387 D. Winter Is Coming
- Mushroom Scientists(Codeforce)
- codeforce B. Preparing Olympiad (DFS+回溯)/(暴力状压)
- codeforce 121E - Lucky Array
- codeforce Present from Lena 打印菱形
- Codeforce - 402C - Searching for Graph
- codeforce round 247 div.2 B
- codeforce 67C - Sequence of Balls(dp)
- Codeforce Round #400 C 签到题
- Codeforce 题目614AA. Link/Cut Tree(水题,坑精度啊)
- Codeforce 301D - Yaroslav and Divisors
- Codeforce Round 363(Div2)A(Java)
- Codeforce 313C Ilya and Matrix