【dp】codeforces C. Vladik and Memorable Trip
http://codeforces.com/contest/811/problem/C
【题意】
给定一个自然数序列,在这个序列中找出几个不相交段,使得每个段的异或值之和相加最大。
段的异或值这样定义:段中每个不同数字(不重复)相异或。
段有这样的要求:段中任意一个数字不会在段外出现。
【思路】
首先预处理每个数字第一次出现和最后一次出现的位置,这样对于一个区间[l,r]就很容易判断是否为满足题意的段。
然后区间DP,dp[i]表示子序列[1,i]的最大值。
状态转移:对于dp[i],最小值为dp[i-1],即a[i]在任意段外;如果a[i]的最后一次出现位置大于i,那么没有更新的余地;否则,可能找到这样的l,S.T.dp[i]=max(dp[i],dp[l-1]+sum[l,i])。
如何找到这样的l?
首先可以肯定的是l最小为first[a[i]],然后遍历[first[a[i]],last[a[i]]]中的每个数,不断更新l=min(l,first[a[k]])。
那么为什么dp[i]不可能是dp[j]+sum[j-1,i](j<l)?
因为这样的j一定不满足[j,i]是一个满足题意的段.
如果last[a[j]]<last[a[i]],那么刚刚在遍历[first[a[i]],last[a[i]]]的时候应该已经找到j,即j>=l,矛盾
如果last[a[j]]>last[a[i]],这样的段也不满足题意。
【TLE】
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <ctime>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
const int maxn=;
int a[maxn];
int fir[maxn];
int last[maxn];
int dp[maxn]; int check(int l,int r)
{
int vis[maxn];
memset(vis,,sizeof(vis));
for(int i=l;i<=r;i++)
{
if(last[a[i]]>r||fir[a[i]]<l)
{
return -;
}
}
int x=;
for(int i=l;i<=r;i++)
{
if(!vis[a[i]])
{
x^=a[i];
vis[a[i]]=;
}
}
return x;
}
int main()
{
while(~scanf("%d",&n))
{
memset(dp,,sizeof(dp));
memset(fir,,sizeof(fir));
memset(last,,sizeof(last));
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
if(!fir[a[i]])
{
fir[a[i]]=i;
}
last[a[i]]=i;
}
for(int i=;i<=n;i++)
{
// cout<<fir[a[i]]<<" "<<last[a[i]]<<endl;
}
for(int i=;i<=n;i++)
{
dp[i]=dp[i-];
for(int k=;k<=i;k++)
{
int num=check(k,i);
if(num>)
{
dp[i]=max(dp[i],dp[k-]+num);
}
}
// printf("dp[%d]=%d\n",i,dp[i]);
}
cout<<dp[n]<<endl; }
return ;
}
一开始没想到怎样找l的方法,直接枚举,时间复杂度O(n^3)(1^2+2^2+.....+n^2=n(n+1)(2n+1)/6)
【Accepted】
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <ctime>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
const int maxn=;
int a[maxn];
int fir[maxn];
int last[maxn];
int dp[maxn]; int sum(int l,int r)
{
int vis[maxn];
memset(vis,,sizeof(vis));
int x=;
for(int i=l;i<=r;i++)
{
if(!vis[a[i]])
{
x^=a[i];
vis[a[i]]=;
}
}
return x;
}
int main()
{
while(~scanf("%d",&n))
{
memset(dp,,sizeof(dp));
memset(fir,,sizeof(fir));
memset(last,,sizeof(last));
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
if(!fir[a[i]])
{
fir[a[i]]=i;
}
last[a[i]]=i;
}
for(int i=;i<=n;i++)
{
dp[i]=dp[i-];
if(last[a[i]]==i)
{
int l=fir[a[i]];
bool flag=true;
for(int k=l+;k<last[a[i]];k++)
{
if(last[a[k]]>i)
{
flag=false;
break;
}
l=min(l,fir[a[k]]);
}
if(flag)
{
dp[i]=max(dp[i],dp[l-]+sum(l,i));
}
}
}
cout<<dp[n]<<endl;
}
return ;
}
【dp】codeforces C. Vladik and Memorable Trip的更多相关文章
- CodeForces - 811C Vladik and Memorable Trip(dp)
C. Vladik and Memorable Trip time limit per test 2 seconds memory limit per test 256 megabytes input ...
- Codeforces 811C Vladik and Memorable Trip (区间异或最大值) (线性DP)
<题目链接> 题目大意: 给你n个数,现在让你选一些区间出来,对于每个区间中的每一种数,全部都只能出现在这个区间. 每个区间的价值为该区间不同的数的异或值之和,现在问你这n个数最大的价值是 ...
- CodeForces 811C Vladik and Memorable Trip
$dp$. 记录$dp[i]$表示以位置$i$为结尾的最大值. 枚举最后一段是哪一段,假设为$[j,i]$,那么可以用$max(dp[1]...dp[j-1]) + val[j][i]$去更新$dp[ ...
- [CodeForces - 1225E]Rock Is Push 【dp】【前缀和】
[CodeForces - 1225E]Rock Is Push [dp][前缀和] 标签:题解 codeforces题解 dp 前缀和 题目描述 Time limit 2000 ms Memory ...
- 【CF1256】Codeforces Round #598 (Div. 3) 【思维+贪心+DP】
https://codeforces.com/contest/1256 A:Payment Without Change[思维] 题意:给你a个价值n的物品和b个价值1的物品,问是否存在取物方案使得价 ...
- Kattis - honey【DP】
Kattis - honey[DP] 题意 有一只蜜蜂,在它的蜂房当中,蜂房是正六边形的,然后它要出去,但是它只能走N步,第N步的时候要回到起点,给出N, 求方案总数 思路 用DP 因为N == 14 ...
- HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】
HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...
- HDOJ 1501 Zipper 【DP】【DFS+剪枝】
HDOJ 1501 Zipper [DP][DFS+剪枝] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
- HDOJ 1257 最少拦截系统 【DP】
HDOJ 1257 最少拦截系统 [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
随机推荐
- Jquary基础
基本知识: 就是一个JS函数包 选择器:基本选择器: 基本:ID选择器 “#” , Class选择器 “.”,标签选择器 “标签名” 组合:并列用“,”隔开 后代用空格隔开 过滤选择器:基本过滤: ...
- CF781A Andryusha and Colored Balloons
题意: Andryusha goes through a park each day. The squares and paths between them look boring to Andryu ...
- 将vue-cli项目配置在nginx上
登录使用的是node.js搭建的注册登录接口,关于对数据库的读写则是用spring boot的框架来实现的. 1.首先是vue-cli项目里的前端页面的配置: location / { root ...
- 一份最贴近真实面试的Java基础面试题
这是一份Java基础知识的面试题.在网上的关于Java的面试题数不胜数,但认真看过感觉大多数都没有实用性,有很多是面试官根本就不会问到的,那些已经脱离了实际开发的技术问题.而这份资料来源自一份个人觉得 ...
- oid和节点名称
由于单篇文档最大字限制是40000个字符,不能将OID附上,因此写出我是如何得到这些OID的. 1.安装NET-SNMP yum install net-snmp yum install net-sn ...
- php中include_path配置
在php.ini中可配置include_path来达到在任何文件中都可以直接引入该目录下文件 include_path = ".:/usr/share/php:/var/www/phpxwl ...
- Android(java)学习笔记170:服务(service)之服务的生命周期 与 两种启动服务的区别
1.之前我们在Android(java)学习笔记171:Service生命周期 (2015-08-18 10:56)说明过,可以回头看看: 2.Service 的两种启动方法和区别: (1)Servi ...
- 约瑟夫环(java)
问题描述:n个人围成一圈,每隔k个杀死一个,问最后的幸存者的编号 假设标号是0 ~ n-1,幸存者是f[n] 1.特殊情况:f[1]=0 2.一般情况:f[n] = (f[n-1]+k)%n 游戏开始 ...
- upload 上传 加token 在 :headers='headers' 注意 不要直接写$refs.upload.headers = {} 这样vue会警告 修改组件内部变量
upload 上传 加token 在 :headers='headers' 注意 不要直接写$refs.upload.headers = {} 这样vue会警告 修改组件内部变量 <Upload ...
- python django项目断点调试