Codeforces Round #426 (Div. 2)
来源:互联网 发布:安卓软件破解 编辑:程序博客网 时间:2024/06/05 05:54
题意:给你一个序列,要你将它分成k块,每个块的权值等于里面数字种类,求最大的权值和。
思路:讲真,这题难度有点大,看第一眼很容易想出O(k*n^2)的dp方法。如果想不出来那么你dp可能还没入门。。。dp[i][j]第i个当前末尾为i节点已经分成了j块,那么有动态转移方程:dp[i][j]=max(dp[i][j],dp[x][j-1]+val[x+1][i]),0<x<i,val表示区间权值,那么再进一步想想怎么优化,因为我们要求最大值,所以我们可以考虑用线段树维护最大值,每次扫过一个位置只有一段区间的val会+1,所以每次扫过一个点更新一下线段树即可,因为有k块,所以要建k个线段树,本来我想敲的了,然后我又怕超内存,而且我也懒,又想了一下,因为每次都需要知道当前块数-1的信息,所以先枚举块数后枚举位置来递推,通过滚动每次只需建一个线段树,不过实际总的来说还是建了k棵,不过是用了1棵树的内存,大概就是这样,下面给代码:
#include<bits/stdc++.h> using namespace std;typedef long long LL;//const LL MOD=1e9+7;#define inf 0x3f3f3f3f#define lowerbit(x) x&(-x)#define maxn 35005int dp[maxn];int maxnum[maxn<<2],mark[maxn<<2],Left[maxn],a[maxn],vis[maxn];void build(int l,int r,int now){mark[now]=0;if(l==r){maxnum[now]=dp[l];return;}int mid=l+r>>1;build(l,mid,now<<1);build(mid+1,r,now<<1|1);maxnum[now]=max(maxnum[now<<1],maxnum[now<<1|1]);}void lazymark(int now){maxnum[now << 1] += mark[now]; mark[now << 1] += mark[now]; maxnum[now << 1 | 1] += mark[now]; mark[now << 1 | 1] += mark[now]; mark[now] = 0; }void update(int l1, int r1, int l2, int r2, int now){ if (l2 <= l1&&r2 >= r1){ maxnum[now] += 1; mark[now]++; return; } int mid = l1 + r1 >> 1; if (mark[now]) lazymark(now); if (l2 <= mid) update(l1, mid, l2, r2, now << 1); if (r2 > mid) update(mid + 1, r1, l2, r2, now << 1 | 1); maxnum[now] = max(maxnum[now << 1], maxnum[now << 1 | 1]); } int query(int l1,int r1,int l2,int r2,int now){if (l2 <= l1&&r2 >= r1) return maxnum[now]; int mid = l1 + r1 >> 1; if (mark[now]) lazymark(now); int a=0,b=0; if(l2<=mid) a=query(l1,mid,l2,r2,now<<1); if(r2>mid) b=query(mid+1,r1,l2,r2,now<<1|1); return max(a,b);}int main(){int n,k;scanf("%d%d",&n,&k);memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++){ scanf("%d", &a[i]); Left[i] = vis[a[i]]; vis[a[i]] = i; } for(int i=1;i<=k;i++){ build(0,n,1);for(int j=i;j<=n;j++){update(0,n,Left[j],j-1,1);dp[j]=query(0,n,0,j-1,1);}}printf("%d\n",dp[n]);}
阅读全文
1 0
- Codeforces Round #426 (Div. 2)
- Codeforces Round #426 (Div. 2)
- Codeforces Round #426 (Div. 2)
- Codeforces Round #426 (Div. 2)
- Codeforces Round #426 (Div. 2)
- Codeforces Round #426 (Div. 2) B
- Codeforces Round #426 (Div. 2) C
- Codeforces Round #426 (Div. 2) C
- Codeforces Round #426 (Div. 2)(A+B)
- Codeforces Round #426 (Div. 2)比赛总结
- Codeforces Round #426 (Div. 2) C
- Codeforces Round #102 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #104 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #107 (Div. 2)
- 阿里巴巴大数据实践之数据建模
- 手机号匹配并打星号
- gevent的调度流程
- 验证日期的正则表达式加入闰年的判断以及思路分析
- java调用本地浏览器打开网页
- Codeforces Round #426 (Div. 2)
- 实体类对象的三种状态
- 分布式机器学习平台比较
- Google Protobuf Java API详解
- [集成学习] bagging和boosting
- 在谷歌浏览器中安装charset.crx离线Chrome插件,修改编码用
- EXCEL数据类型
- ios 加载本地网页 css js 无法显示问题
- windows 启动停止 java进程