这道题考试的时候先打了个dfs暴力。又打了个O(n²)的动规。然后竟然心血来潮拍了一下。。明明知道过不去的。。。然后水了50分(20个测试点这么多啊啊啊啊)。

因为它已经提前给你如果长度为i时下一位的符号,显然O(n²)的打法大家都会打。

for(i..1..n)
  for(j..1..i-1)
     if(符合条件)
       f[i]=max(f[i],f[j]+1);

然后我们就考虑如何降低复杂度。

因为我们要求的是符合条件的前缀最大值,可以使用线段树来维护。

线段树的下标是权值,内容是最长长度。

一共三种情况:<,>,=。

我们需要单独存这三种情况。以大于为例:

线段树里面存的是某个权值下,下一位是大于号的所有最优长度。

至于等于可以用数组记录,不必用线段树。

然后我们更新的时候,对于f[i]=max{权值(0,a[i]-1)中所有后边符号是小于的最大值,权值(a[i]+1,inf)中所有后边符号是大于的最大值,相等的最大值}+1;

再根据f[i]的长度确定后边一位是什么符号,再把f[i]加入对应的线段树中。

复杂度O(n㏒n)。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define N 2020200
int a[N],n,k;
char s[N];
int cun[N],f[N];
int ans;
int ma;
struct haha{
	int left,right,num;
};
haha treeda[N*4];haha treexiao[N*4];
void buildda(int x,int left,int right){
	treeda[x].left=left;
	treeda[x].right=right;
	if(left==right){
		treeda[x].num=0;
		return;
	}
	int mid=(left+right)>>1;
	buildda(x*2,left,mid);
	buildda(x*2+1,mid+1,right);
}
int queryda(int left,int right,int root){
	if(treeda[root].left==left&&treeda[root].right==right){
		return treeda[root].num;
	}
	int mid=(treeda[root].left+treeda[root].right)>>1;
	if(right<=mid){
		return queryda(left,right,root*2);
	}
	else{
		if(left>mid){
			return queryda(left,right,root*2+1);
		}
		else{
			return max(queryda(left,mid,root*2),queryda(mid+1,right,root*2+1));
		}
	}
}
void changeda(int x,int num,int root){
	if(treeda[root].left==treeda[root].right){
		treeda[root].num=num;
		return;
	}
	treeda[root].num=max(treeda[root].num,num);
	if(x<=treeda[root*2].right)
	  changeda(x,num,root*2);
	else
	  changeda(x,num,root*2+1);
}
void buildxiao(int x,int left,int right){
	treexiao[x].left=left;
	treexiao[x].right=right;
	if(left==right){
		treexiao[x].num=0;
		return;
	}
	int mid=(left+right)>>1;
	buildxiao(x*2,left,mid);
	buildxiao(x*2+1,mid+1,right);
}
int queryxiao(int left,int right,int root){
	if(treexiao[root].left==left&&treexiao[root].right==right){
		return treexiao[root].num;
	}
	int mid=(treexiao[root].left+treexiao[root].right)>>1;
	if(right<=mid){
		return queryxiao(left,right,root*2);
	}
	else{
		if(left>mid){
			return queryxiao(left,right,root*2+1);
		}
		else{
			return max(queryxiao(left,mid,root*2),queryxiao(mid+1,right,root*2+1));
		}
	}
}
void changexiao(int x,int num,int root){
	if(treexiao[root].left==treexiao[root].right){
		treexiao[root].num=num;
		return;
	}
	treexiao[root].num=max(treexiao[root].num,num);
	if(x<=treexiao[root*2].right)
	  changexiao(x,num,root*2);
	else
	  changexiao(x,num,root*2+1);
}
int deng[N];
int Max(int a,int b,int c){
	return max(max(a,b),c);
}
int main(){
	//freopen("mot.in","r",stdin);
	//freopen("mot.out","w",stdout);
	scanf("%d%d",&n,&k);
	pos(i,1,n){
		scanf("%d",&a[i]);
		ma=max(ma,a[i]);
	}
	pos(i,1,k){
		scanf("%s",&s[i]);
	}
	pos(i,1,n-1){
		cun[i]=s[(i-1)%k+1];
	}
	buildxiao(1,0,ma);
	buildda(1,0,ma);
	pos(i,1,n){
		int tmp1,tmp2;
		if(a[i]==ma){
			tmp1=1;
		}
		else{
			tmp1=queryda(a[i]+1,ma,1);
		}
		if(a[i]==0){
			tmp2=1;
		}
		else{
			tmp2=queryxiao(0,a[i]-1,1);
		}
		f[i]=Max(tmp1,tmp2,deng[a[i]])+1;
		if(cun[f[i]]=='>'){
			changeda(a[i],f[i],1);
		}
		if(cun[f[i]]=='<'){
			changexiao(a[i],f[i],1);
		}
		if(cun[f[i]]=='='){
			deng[a[i]]=max(deng[a[i]],f[i]);
		}
		ans=max(ans,f[i]);
	}
	printf("%d",ans);
	return 0;
}

  

[Poi2010]Monotonicity 2 线段树的更多相关文章

  1. BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】

    BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...

  2. 【BZOJ2090/2089】[Poi2010]Monotonicity 2 动态规划+线段树

    [BZOJ2090/2089][Poi2010]Monotonicity Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度 ...

  3. [补档][Poi2010]Monotonicity 2

    [Poi2010]Monotonicity 2 题目 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. 选出一个长度为L的子序列(不要求连续),要求这个子序列 ...

  4. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  5. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  6. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  7. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  8. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  9. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

随机推荐

  1. Java基础(1) - 语法 & 概念

    Java基础语法 基础 1. Java对大小写敏感 2. Java注释 //单行注释 这是一行注释 /* 这里是多行 注释 */ /** 这里是文档注释 @author 0o晓月メ */ 3. 访问修 ...

  2. 如何判断浏览器为ie10以上

    如果针对ie10 以上单独写css样式的话,ie10以上已经不提供 <!--[if ...]><![endif]--> 这种方法去操作了,所以可以用css媒体查询的方法@med ...

  3. 对X86汇编的理解与入门

    本文描述基本的32位X86汇编语言的一个子集,其中涉及汇编语言的最核心部分,包括寄存器结构,数据表示,基本的操作指令(包括数据传送指令.逻辑计算指令.算数运算指令),以及函数的调用规则.个人认为:在理 ...

  4. JanaScript预解析

    JS预解析是什么?      在当前的作用域下,js运行之前.会有带有 var 和 function关键字的代码事先声明,      并在内存中安排好,然后从上到下的执行js代码. JS预解析 js逐 ...

  5. 005.Getting started with ASP.NET Core MVC and Visual Studio -- 【VS开发asp.net core mvc 入门】

    Getting started with ASP.NET Core MVC and Visual Studio VS开发asp.net core mvc 入门 2017-3-7 2 分钟阅读时长 本文 ...

  6. CSS3-loading动画(五)

    CSS3-loading加载动画 在线示例demo:http://liyunpei.xyz/loading.html 之前发了四篇,二十二个效果,今天再分享六个效果,总计二十八个效果. 二十三.效果二 ...

  7. 20170709_python_学习记录

    a='ABC';变量赋值时发生了什么 1.在内存中创建一个字符串'ABC' 2.在内存中创建一个变量a指向字符串'ABC' list [] 相当于数组 指向可以变动 str[1,2,3,4] str. ...

  8. spark-2.2.0安装和部署——Spark集群学习日记

    前言 在安装后hadoop之后,接下来需要安装的就是Spark. scala-2.11.7下载与安装 具体步骤参见上一篇博文 Spark下载 为了方便,我直接是进入到了/usr/local文件夹下面进 ...

  9. 小型 Web 页项目打包优化方案

    背景   目前团队中新的 Web 项目基本都采用了 Vue 或 React ,加上 RN,这些都属于比较重量级的框架,然而对于小型 Web 页面,又显得过大.早期的一些项目则使用了较原始的 HTML ...

  10. Node.js安装及环境配置之Windows篇

    Node.js安装及环境配置之Windows篇   一.安装环境 1.本机系统:Windows 10 Pro(64位)2.Node.js:v6.9.2LTS(64位) 二.安装Node.js步骤 1. ...