bzoj1318[spoj 744] Longest Permutation
题意
给出一个长度为n的,所有元素大小在[1,n]的整数数列,要求选出一个尽量长的区间使得区间内所有元素组成一个1到区间长度k的排列,输出k的最大值
n<=1e5
分析
不会做,好菜啊.jpg
学习了西方那一套理论,里面别人的题解写得挺吼的但是没多少人点赞23333.
外来的和尚好念经
一个合法排列必然包括一个1.那么我们可以枚举这个1的位置,既然包含了这个1就不能包含其他的1,所以我们可以找出这个1左边的第一个1的位置L(如果没有就是0)和右边的第一个1的位置R(如果没有就是n+1).包括这个1的排列左端不能超过L+1,右端不超过R-1.
于是我们把问题转化成若干个子问题,每个子问题处理的区间中只有一个1.所有子问题的区间总长之和是O(n)的,因为原序列中的每个位置只会对最多两个子问题贡献1的区间长度.
现在考虑怎样解决一个子问题.
一个长度为L的序列如果合法,那么序列中的最大值等于L且序列中没有重复元素.
在一个子问题中,区间内只有一个1,那么选出的序列必然包含这个1,而选出的序列中的最大值可以在这个1的左侧,也可以在这个1的右侧.由对称性,只考虑最大值在左侧的情况.在右侧的情况反着跑一遍就行.
如果最大值在左侧,我们可以枚举选出的序列的左端点l,那么从1的位置一直到l的最大值就是1左侧的最大值,因为我们假设最大值在1的左侧,所以现在我们也认为这个最大值是整个选出的序列的最大值.那么选出的序列的长度也就确定了,序列的右端点r也就确定了,我们只需判断[l,r]是不是一个合法的区间.也就是判一下[l,r]的最大值是不是在1的位置的左侧,判一下[l,r]中是否有重复元素.如果是合法的,就用r-l+1更新答案.
求最大值只需要预处理Max[i]表示从1所在的位置一直到i的最大值.
判断[l,r]是否有重复元素只需预处理lsame[i]表示i左侧第一个数值和a[i]相等的位置,如果l<=i<=r的所有i中存在一个i使得lsame[i]>=l,那么有重复元素,否则没有.
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=300005;
int a[maxn];
int lsame[maxn],rsame[maxn];
int pos[maxn];
int ans=0;
int Max[maxn],MaxLsame[maxn];
void work(int s,int L,int R){
  if(ans==0)ans=1;
  Max[s]=a[s];
  for(int i=s-1;i>=L;--i)Max[i]=max(Max[i+1],a[i]);
  for(int i=s+1;i<=R;++i)Max[i]=max(Max[i-1],a[i]);
  MaxLsame[s]=lsame[s];
  for(int i=s-1;i>=L;--i)MaxLsame[i]=max(MaxLsame[i+1],lsame[i]);
  for(int i=s+1;i<=R;++i)MaxLsame[i]=max(MaxLsame[i-1],lsame[i]);
  for(int i=s-1;i>=L;--i){//maximum number left of s
    if(MaxLsame[i]>=i)continue;
    int length=Max[i];
    int r=i+length-1;
    if(r>R)continue;
    if(MaxLsame[r]>=i||Max[r]>=Max[i])continue;
    if(length>ans)ans=length;
  }
  for(int i=s+1;i<=R;++i){//maximum number right of s
    if(MaxLsame[i]>=s)continue;
    int length=Max[i];
    int l=i-length+1;
    if(l<L)continue;
    if(MaxLsame[l]>=l||MaxLsame[i]>=l||Max[l]>=Max[i])continue;
    if(length>ans)ans=length;
  }
}
int main(){
  int n;scanf("%d",&n);
  for(int i=1;i<=n;++i)scanf("%d",a+i);
  for(int i=1;i<=n;++i){
    lsame[i]=pos[a[i]];pos[a[i]]=i;
  }
  for(int i=1;i<=n;++i)pos[i]=n+1;
  for(int i=n;i>=1;--i){
    rsame[i]=pos[a[i]];pos[a[i]]=i;
  }
  for(int i=1;i<=n;++i){
    if(a[i]==1){
      work(i,lsame[i]+1,rsame[i]-1);
    }
  }
  printf("%d\n",ans);
  return 0;
}
												
											bzoj1318[spoj 744] Longest Permutation的更多相关文章
- 【bzoj1318】[Spoj744] Longest Permutation(乱搞)
		
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1318 这道题的大意是要求一个长度为len,并包含1~len所有数,并使len最大的子区 ...
 - bzoj 1318: [Spoj744] Longest Permutation 智商题
		
1318: [Spoj744] Longest Permutation Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 361 Solved: 215 ...
 - 【SPOJ】Longest Common Substring II (后缀自动机)
		
[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...
 - 【SPOJ】Longest Common Substring(后缀自动机)
		
[SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...
 - 【SPOJ】Longest Common Substring II
		
[SPOJ]Longest Common Substring II 多个字符串求最长公共子串 还是将一个子串建SAM,其他字符串全部跑一边,记录每个点的最大贡献 由于是所有串,要对每个点每个字符串跑完 ...
 - 【SPOJ】Longest Common Substring
		
[SPOJ]Longest Common Substring 求两个字符串的最长公共子串 对一个串建好后缀自动机然后暴力跑一下 废话 讲一下怎么跑吧 从第一个字符开始遍历,遍历不到了再沿着\(pare ...
 - SPOJ Another Longest Increasing Subsequence Problem  三维最长链
		
SPOJ Another Longest Increasing Subsequence Problem 传送门:https://www.spoj.com/problems/LIS2/en/ 题意: 给 ...
 - SPOJ 1812 Longest Common Substring II(后缀自动机)(LCS2)
		
A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...
 - SPOJ LCS2 - Longest Common Substring II
		
LCS2 - Longest Common Substring II A string is finite sequence of characters over a non-empty finite ...
 
随机推荐
- 20155318 2016-2017-2 《Java程序设计》第二周学习总结
			
20155318 2016-2017-2 <Java程序设计>第二周学习总结 教材学习内容总结 Java编程风格 基本语法与C相似:调用main函数写public static void ...
 - 20145226夏艺华 《Java程序设计》实验报告一
			
实验一 Java开发环境的熟悉(Linux + IDEA) 实验内容 使用JDK编译.运行简单的Java程序: 使用Eclipse 编辑.编译.运行.调试Java程序. 实验步骤 (一)命令行下Jav ...
 - primary key和unique的区别
			
定义了 UNIQUE 约束的字段中不能包含重复值,可以为一个或多个字段定义 UNIQUE 约束.因此,UNIQUE 即可以在字段级也可以在表级定义, 在 UNIQUED 约束的字段上可以包含空值.OR ...
 - XAMPP设置tomcat自启动时,报无效的Win32程序
			
最近给一个客户开发了一套系统,需要在内网中部署.系统是Java + Tomcat7 + mysql开发的. 考虑到客户内网不能上网的情况下,想使用XAMPP的便捷性,给客户进行部署.因为只需要Tomc ...
 - hive 数据导入
			
Hive的几种常见的数据导入方式这里介绍四种:(1).从本地文件系统中导入数据到Hive表:(2).从HDFS上导入数据到Hive表:(3).从别的表中查询出相应的数据并导入到Hive表中:(4).在 ...
 - javaweb(二十)——JavaBean总结
			
一.什么是JavaBean JavaBean是一个遵循特定写法的Java类,它通常具有如下特点: 这个Java类必须具有一个无参的构造函数 属性必须私有化. 私有化的属性必须通过public类型的方法 ...
 - 身份证扫描识别/身份证OCR识别的正确姿势,你get到了吗?
			
自从国家规定电信实名制之后,实名制已经推广到各个领域:办理通信业务需要实名制.银行开户需要实名制.移动支付需要实名制,就连注册个自媒体账户都需要实名制. 而实名制的背后,就是身份证信息的采集和录入验证 ...
 - vue cli 3      +jquery
			
const webpack = require('webpack')module.exports = { // baseUrl type:{string} default:'/' // 将部署应用程序 ...
 - 随笔1-本想吐槽cnblog编辑器,但是今天猛然发现它竟然这么干净简洁
			
日常用写作编辑器 多少和我一样有选择综合征的? 不愿意写博客的其中一个非常重要的原因是编辑器不好用! 博客的迁移是相当麻烦的! 所以定下cnblog写东西也是一种勇气!鼓励.... FlashNote ...
 - LeetCode--147.对链表进行插入排序
			
题目描述: 插入排序的动画演示如上.从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示). 每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中. 插入排序算法 ...