【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 ...
随机推荐
- MySQL防止重复插入记录SQL
INSERT INTO sysuser(') DUAL:表示虚拟表 sysuser:表名称
- canvas基础绘制-绚丽倒计时
效果图: html: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- 浅析Statement和PreparedStatement的区别
当我们使用java程序来操作sql server时会使用到Statement和PreparedStatement,俩者都可以用于把sql语句从java程序中发送到指定数据库,并执行sql语句.那么如何 ...
- Javaweb学习笔记5—Cookie&Session
今天来讲javaweb的第五阶段学习. Cookie和Session同样是web开发常用到的地方. 老规矩,首先先用一张思维导图来展现今天的博客内容. ps:我的思维是用的xMind画的,如果你对我的 ...
- JavaScript 声明全局变量与局部变量
一.JavaScript 声明全局变量的三种方式: 声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为全局变量,否则在function声明的是局部变量.该方式即 ...
- 纯css滚动公告栏目
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 如何通过Java代码判断当前的环境是否支持JRE 9
JDK9已经出来有一段时间了,因此很多流行的Java应用纷纷增添了对JDK9乃至JDK10的支持,比如Tomcat. 我们通过这个链接下载最新的Tomcat源文件包,总共7MB: https://to ...
- C#飞行棋总结
以下是掷色子的一个代码,比较有代表性,里面的逻辑和内容都已注释,可通过注释了解这一方法的运作模式. public static void RowTouZi(int playerPos) //掷色子 { ...
- WPF知识点全攻略00- 目录
知识点目录如下: 1.WPF相对WinFrom的优缺点 2.WPF体系结构 3.XAML 4.XAML页面布局 5.XAML内容控件 6.WPF中的“树” 7.Binding 8.依赖属性 9.附加属 ...
- chrome ubuntu启动不了
安装好后,点击图标没反应 用命令行运行chrome并显示log:google-chrome --enable-logging=stderr --log-level=4 报错如下: 解决:安装更高版本的 ...