[Poi2010]Monotonicity 2 线段树
这道题考试的时候先打了个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 线段树的更多相关文章
- BZOJ2090: [Poi2010]Monotonicity 2【线段树优化DP】
BZOJ2090: [Poi2010]Monotonicity 2[线段树优化DP] Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. ...
- 【BZOJ2090/2089】[Poi2010]Monotonicity 2 动态规划+线段树
[BZOJ2090/2089][Poi2010]Monotonicity Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度 ...
- [补档][Poi2010]Monotonicity 2
[Poi2010]Monotonicity 2 题目 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. 选出一个长度为L的子序列(不要求连续),要求这个子序列 ...
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
- codevs 1080 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
- codevs 1082 线段树区间求和
codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...
- PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树
#44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...
随机推荐
- JAVA基础——类和对象
java类与对象学习笔记 一.成员变量和局部变量 (1)定义 1.成员变量 在类中定义,用来描述对象将要有什么.(默认的成员变量值为0) 2.局部变量 在类的方法中定义,在方法中临时保存数据. 演示示 ...
- JAVA基础——最简单的多重循环程序
Java 循环语句之多重循环 循环体中包含循环语句的结构称为多重循环.三种循环语句可以自身嵌套,也可以相互嵌套,最常见的就是二重循环.在二重循环中,外层循环每执行一次,内层循环要执行一圈. 如下所示: ...
- 如何让局域网内的其他电脑访问本机的mysql
测试电脑:本机ip是125.216.250.67 其他电脑 125.216.250.68 第一步:先用其他电脑ping本机,看能否ping通 如上图即为成功ping通了 第二步:开放mysql的全向 ...
- Navigation Controller 创建方法
添加Navigation Controller的方法主要有两种: 第一种:主要是通过在storyboard中拖入Object library 中的Navigation Controller 第二种方法 ...
- LR监控Windows Server 2008 R2系统资源提示“指定的网络名不可用。”
问题现象: LR监控远程服务器Window Server 2008 R2 系统资源,提示“Monitor name :Windows Resources. Cannot connect to mach ...
- JDBC02 利用JDBC连接数据库【使用数据库连接池】
目录 1/2/3 Statement 和 Preparedstatement 的区别 4 读取properties配置文件 5 数据库连接池 6 利用数据库连接池连接数据库 1 使用Statemen ...
- BufferedWriter
package JBJADV003;import java.io.*;public class BufferedWriterTest { public static void main(String[ ...
- Java系列 - 用Java8新特性进行Java开发太爽了
本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome/ 前言 从开始写博客到现在已经过去3个 ...
- 实时音视频互动系列(上):又拍云UTUN网络详解
如何定义实时音视频互动, 延迟 400ms 内才能无异步感 实时音视频互动如果存在1秒左右的延时会给交流者带来异步感,必须将视频播放延迟限制在400ms以内,才能给用户较好的交互体验. 当延迟控制在4 ...
- Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂)
Luogu 1349 广义斐波那契数列(递推,矩阵,快速幂) Description 广义的斐波那契数列是指形如\[A_n=p*a_{n-1}+q*a_{n-2}\]的数列.今给定数列的两系数p和q, ...