博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces Round #416 (Div. 2) C. Vladik and Memorable Trip
阅读量:5132 次
发布时间:2019-06-13

本文共 1554 字,大约阅读时间需要 5 分钟。

Codeforces Round #416 (Div. 2) C. Vladik and Memorable Trip(DP)

题目链接:

题意:给你一个数字串,让你把他分开成几个不重叠的子数字串,每个子数字串里的每一个数字需要全部在这个子数字串的区间内部,比如5,3,2,3,2,1,3对于这个数列我们取2,3,2,1作为一个子数字串区间是不对的,因为并不是所有的3都在这个区间里面。如果我们取3,2,3,2,1,3这样的区间就是对的,因为这个区间里面所有的不同的数都在这个区间里面,我们对每个区间的数不同的数异或一遍。然后把所有子数字串区间的异或和相加求这个和的最大值。

思路:

  1.我们要知道我们所选区间内部是否包含了这个数在整个数字串里面的全部数量。我们就需要知道每一个数在整个子串里面第一个出现的位置,和最后一个出现的位置,这就需要预处理一下。

  2.我们枚举i作为序列的结尾,然后反向枚举j作为序列的开头。如果[j,i]区间内包含了所有[j,i]内的所有的数在整个数字串中的全部数量。那么我们就可以 dp[i]=max(dp[i],dp[j-1]+sum);

  3.否则我们善意的认为dp[i]=dp[i-1]

  4.一路维护dp[i]的最大值。

代码:

//Author: xiaowuga#include 
#define maxx INT_MAX#define minn INT_MIN#define inf 0x3f3f3f3fconst long long N= 5001;using namespace std;typedef long long L;int main() { ios::sync_with_stdio(false);cin.tie(0); int n; cin>>n; int a[N]; for(int i=1;i<=n;i++) cin>>a[i]; int fir[N]={
0},las[N]={
0}; for(int i=1;i<=n;i++) las[a[i]]=i;//最后一个出现地方 for(int i=n;i>=1;i--) fir[a[i]]=i;//最后一个出现的地方 int vis[N]; int dp[N]={
0}; for(int i=1;i<=n;i++){ dp[i]=dp[i-1]; int sum=0; memset(vis,0,sizeof(vis));//去重 int st=fir[a[i]]; for(int j=i;j>=1;j--){ if(vis[a[j]]==0){ if(las[a[j]]>i) break;//如果这个区间没有包含所有的这个数 st=min(st,fir[a[j]]);//[j,i]区间内的元素在数组中第一个元素的出现最早的下标 sum^=a[j];//[j,i]区间内所有不同的元素的异或的结果 vis[a[j]]=1; } if(j<=st) dp[i]=max(dp[i],dp[j-1]+sum); } } cout<
<

 

转载于:https://www.cnblogs.com/xiaowuga/p/7222351.html

你可能感兴趣的文章
java代码编译与C/C++代码编译的区别
查看>>
Bitmap 算法
查看>>
转载 C#文件中GetCommandLineArgs()
查看>>
list control控件的一些操作
查看>>
精读《useEffect 完全指南》
查看>>
SNF快速开发平台MVC-EasyQuery-拖拽生成SQL脚本
查看>>
DrawerLayout实现双向侧滑
查看>>
MySQL入门很简单-触发器
查看>>
LVM快照(snapshot)备份
查看>>
绝望的第四周作业
查看>>
一月流水账
查看>>
数论四大定理
查看>>
npm 常用指令
查看>>
20几个正则常用正则表达式
查看>>
TextArea中定位光标位置
查看>>
非常棒的Visual Studo调试插件:OzCode 2.0 下载地址
查看>>
判断字符串在字符串中
查看>>
hdu4374One hundred layer (DP+单调队列)
查看>>
类间关系总结
查看>>
properties配置文件读写,追加
查看>>