【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 ...
随机推荐
- vs2013转为vs2010项目
1.首先用记事本之类的工具打开.sln文件 打开后会看到如下信息 Format Version 12.00 就是指VS2013 VisualStudioVersion = 12.0.21005.1 指 ...
- [转]Android TCP长连接 心跳机制及实现
背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...
- ubuntu上部署windows开发的dotnet core程序
目标:完成windows上开发的dotnet core程序部署至linux服务器上(Ubuntu 14.04) windows上开发dotnet core很简单,安装好VS2017,建立相关类型的项目 ...
- Oracle错误 1053: 该服务没有响应启动或控制请求
在服务中,启动oracleDBConsolenewdb服务时,出现了 错误 1053: 该服务没有响应启动或控制请求 在网上查了以后你会发现这是一个非常宽泛的错误,然而我们的建议是去看传说中的orac ...
- CSS 功能简介
CSS的功能主要包括节点管理(Node Management,以下简称NM)和组管理(Group Management,以下简称GM)两部分,都是由守护进程ocssd.bin 来实现的,这是个多线程的 ...
- (转)用@Resource注解完成属性装配
http://blog.csdn.net/yerenyuan_pku/article/details/52858878 前面我们讲过spring的依赖注入有两种方式: 使用构造器注入. 使用属性set ...
- DROP TRIGGER - 删除一个触发器定义
SYNOPSIS DROP TRIGGER name ON table [ CASCADE | RESTRICT ] DESCRIPTION 描述 DROP TRIGGER 将删除所有对一个现存触发器 ...
- DELETE - 删除一个表中的行
SYNOPSIS DELETE FROM [ ONLY ] table [ WHERE condition ] DESCRIPTION 描述 DELETE 从指明的表里删除满足 WHERE 子句的行. ...
- windows安装tensorflow的一个教训
今天没什么课,然后就准备安装tensorflow. 看了一下教程,就去做了. 然后就犯了错误.网上的教程还是有一些差异的,而我又比较大意,没有很注意到CUDA,cudnn的版本要求,也过于高估自己cp ...
- 检查bug
用selective_search生成的坐标是(ymin,xmin,ymax,xmax),并且是从1开始的,不是从0 这是cache中的gt数据,明显看到有65535,说明很有可能是0-1变成了655 ...