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的更多相关文章

  1. 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 ...

  2. Codeforces 811C Vladik and Memorable Trip (区间异或最大值) (线性DP)

    <题目链接> 题目大意: 给你n个数,现在让你选一些区间出来,对于每个区间中的每一种数,全部都只能出现在这个区间. 每个区间的价值为该区间不同的数的异或值之和,现在问你这n个数最大的价值是 ...

  3. CodeForces 811C Vladik and Memorable Trip

    $dp$. 记录$dp[i]$表示以位置$i$为结尾的最大值. 枚举最后一段是哪一段,假设为$[j,i]$,那么可以用$max(dp[1]...dp[j-1]) + val[j][i]$去更新$dp[ ...

  4. [CodeForces - 1225E]Rock Is Push 【dp】【前缀和】

    [CodeForces - 1225E]Rock Is Push [dp][前缀和] 标签:题解 codeforces题解 dp 前缀和 题目描述 Time limit 2000 ms Memory ...

  5. 【CF1256】Codeforces Round #598 (Div. 3) 【思维+贪心+DP】

    https://codeforces.com/contest/1256 A:Payment Without Change[思维] 题意:给你a个价值n的物品和b个价值1的物品,问是否存在取物方案使得价 ...

  6. Kattis - honey【DP】

    Kattis - honey[DP] 题意 有一只蜜蜂,在它的蜂房当中,蜂房是正六边形的,然后它要出去,但是它只能走N步,第N步的时候要回到起点,给出N, 求方案总数 思路 用DP 因为N == 14 ...

  7. HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】

    HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...

  8. HDOJ 1501 Zipper 【DP】【DFS+剪枝】

    HDOJ 1501 Zipper [DP][DFS+剪枝] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...

  9. HDOJ 1257 最少拦截系统 【DP】

    HDOJ 1257 最少拦截系统 [DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...

随机推荐

  1. P1851 好朋友

    题目背景 小可可和所有其他同学的手腕上都戴有一个射频识别序列号码牌,这样老师就可以方便的计算出他们的人数.很多同学都有一个“好朋友” .如果 A 的序列号的约数之和恰好等于B 的序列号,那么 A的好朋 ...

  2. JDK NIO SelectionKey bug

    此bug项目中使用elasticSearch中出现的,原因是,nio事件选择器,在特性内核下以及jdk6版本中,出现不hold线程,死循环获取事件的bug,导致cup使用率过高: 此bug在官网已被修 ...

  3. 新建cordova应用,插件开发教程系列(总目录)

    以下几篇是连续的教程,代码也是连续的,包括如下章节: 新建cordova应用 https://www.cnblogs.com/cannel/p/11074359.html 使用cordova把h5应用 ...

  4. mysql5.7.25集群部署和方案设计(附PXC一键部署脚本)

    还记得我们之前部署mysql集群有多麻烦嘛?波哥来救你们啦!~ 我已将项目上传到了我的github仓库中,大家可以点击仓库地址出现的连接登录查看相应的代码!如果觉得不错别忘了转发.点赞哦! 部署步骤: ...

  5. jsp <%@ include %> 例子

    <%@ include %>:所有代码包含进来之后一起进行处理,最终编译成一个servlet. jsp文件中添加top和bottom.jsp页面 empList.jsp <%@ pa ...

  6. 第17周翻译:SQL Server中的事务日志管理的阶梯:第5级:在完全恢复模式下管理日志

    来源:http://www.sqlservercentral.com/articles/Stairway+Series/73785/ 作者:Tony Davis, 2012/01/27 翻译:刘琼滨. ...

  7. 管道命令和xargs的区别(经典解释) 自己的总结

    1. 简介 之所以能用到这个命令,关键是由于很多命令不支 持|管道来传递参数,而日常工作中有有这个必要, 所以就有了xargs命令,例如:find /sbin -perm +700 |ls -l 这个 ...

  8. Eclipse添加默认的JRE

    打开eclipse,依次点击如下选项Window->Preferences-> Java -> Installed JREs.步骤见下图.   选中Installed JREs选项出 ...

  9. CSS 功能简介

    CSS的功能主要包括节点管理(Node Management,以下简称NM)和组管理(Group Management,以下简称GM)两部分,都是由守护进程ocssd.bin 来实现的,这是个多线程的 ...

  10. ACCEPT详解

    NAME 名称 accept - 在一个套接字上接收一个连接 SYNOPSIS 概述 #include <sys/types.h> #include <sys/socket.h> ...