洛谷P4093 [HEOI2016/TJOI2016]序列

题目描述

佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可 。

注意:每种变化最多只有一个值发生变化。在样例输入1中,所有的变化是:

1 2 3 
2 2 3 
1 3 3 
1 1 3
1 2 4 

选择子序列为原序列,即在任意一种变化中均为不降子序列在样例输入2中,所有的变化是:

3 3 3
3 2 3

选择子序列为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要

输入输出格式

输入格式:

输入的第一行有两个正整数n, m,分别表示序列的长度和变化的个数。接下来一行有n个数,表示这个数列原始的状态。接下来m行,每行有2个数x, y,表示数列的第x项可以变化成y这个值。1 <= x <= n。

输出格式:

输出一个整数,表示对应的答案

输入输出样例

输入样例#1:

3 4 
1 2 3 
1 2 
2 3 
2 1 
3 4

输出样例#1:

3

说明

对于20%数据所有数字均为正整数,且小于等于300

对于50%数据所有数字均为正整数,且小于等于3,000

对于100%数据所有数字均为正整数,且小于等于100,000

这道题是DP应该不难看出来。

dp[i]表示选择i以后所能形成的满足条件的子序列的最大值

转移的时候枚举前面的点(j)。

MX[i]表示i号位置能变成的最大值,MI[i]表示i号位置能变成的最小值,a为原序列

这样转移的时候会有两个限制条件

a[i]>=MX[j]a[i]>=MX[j]&&MI[i]>=a[j]

这很明显是个二维偏序问题嘛,用CDQ树套树什么的都可以搞。

树套树的话,将a抽象为x轴,将MX抽象为y轴

转移的时候我们实际是在左下角为(0,0),右上角为MI[i],a[i]的矩阵中查最大值

每次转移对答案的贡献的话实际上只是改变了a[i],mx[i]的值

然后就能很自然的想到树套树了,线段树套线段树或者树状数组套线段树都可以搞

后者常数小一些

线段树的数组一定要开的足够大!!!!

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=6*1e6+10;
const int MAXNN=1e5+10;
const int INF=1e8+10;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int root[MAXN],N,M,MX[MAXNN],MI[MAXNN],a[MAXNN];
struct S
{
    struct node
    {
        int ls,rs,mx;
    }T[MAXN];
    int tot;
    int query(int now,int ll,int rr,int pos)
    {
        if(ll==rr) 
            return T[now].mx;
        int mid=ll+rr>>1;
        if(pos<=mid) 
            return query(T[now].ls,ll,mid,pos);
        else 
            return max( T[T[now].ls].mx , query(T[now].rs,mid+1,rr,pos));    
    }
    void change(int &now,int ll,int rr,int pos,int val)
    {
        if(!now) now=++tot;
        T[now].mx=max(T[now].mx,val);
        if(ll==rr) return ;
        int mid=ll+rr>>1;
        if(pos<=mid) change(T[now].ls,ll,mid,pos,val);
        else          change(T[now].rs,mid+1,rr,pos,val);
    }
}tree;
struct B
{ 
    int N;
    int Tree[MAXNN];
    int lowbit(int p) {return p&(-p);}
    int Query(int k,int val)
    {
        int ans=0;
        while(k) 
        {
            ans=max(ans,tree.query(root[k],1,N,val));
            k-=lowbit(k);
        }
        return ans;
    }
    void Change(int k,int pos,int val)
    {
        while(k<=N)
        {
            tree.change(root[k],1,N,pos,val);
            k+=lowbit(k);
        }
    }
}BIT;
int main()
{
    //freopen("heoi2016_seq.in","r",stdin);
    //freopen("heoi2016_seq.out","w",stdout);
    N=read();M=read();
    for(int i=1;i<=N;i++) MX[i]=MI[i]=a[i]=read();
    for(int i=1;i<=M;i++)
    {
        int x=read(),y=read();
        MX[x]=max(MX[x],y);BIT.N=max(BIT.N,MX[x]);
        MI[x]=min(MI[x],y);
    }
    int ans=0;
    for(int i=1;i<=N;i++)
    {
        int now=BIT.Query(MI[i],a[i])+1;
        BIT.Change(a[i],MX[i],now);
        ans=max(ans,now);
    }
    printf("%d",ans);
    return 0;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏calmound

hust Dating With Girls

http://acm.sdibt.edu.cn:8080/judge/contest/view.action?cid=573#problem/B 题意:求最大权...

2894
来自专栏TensorFlow从0到N

TensorFlow从0到1 - 2 - TensorFlow核心编程

上一篇Hello, TensorFlow!中的代码还未解释,本篇介绍TensorFlow核心编程的几个基本概念后,那些Python代码就很容易理解了。 与Te...

47510
来自专栏与神兽党一起成长

最大子序列和O(N)算法简单分析『神兽必读』

可以看到算法中重要的位置都标注出来了。 显然这个算法有一个for循环,整体时间复杂度可以看作O(N)。 就算法正确性来分析,首先假设这样的输入:-2, -3, ...

3592
来自专栏数据结构与算法

P2280 [HNOI2003]激光炸弹

题目描述 ? 输入输出格式 输入格式: 输入文件名为input.txt 输入文件的第一行为正整数n和正整数R,接下来的n行每行有3个正整数,分别表示 输...

3225
来自专栏和蔼的张星的图像处理专栏

2. 尾部的零

设计一个算法,计算出n阶乘中尾部零的个数 样例 11! = 39916800,因此应该返回 2. 这其实是一个数学题,思路倒是很简单,主要就是找每个数有多...

1313
来自专栏ACM算法日常

交错字符串(动态规划)- leetcode 97

给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

1491
来自专栏人工智能LeadAI

pytorch入门教程 | 第一章:Tensor

1 pytorch安装 安装pytorch之前,需要安装好python,还没安装过python的宝宝请先移步到廖雪峰的python教程,待安装熟悉完之后,再过来...

42110
来自专栏Java3y

Map集合、散列表、红黑树介绍

1883
来自专栏数据结构与算法

51nod1004 n^n的末位数字

题目来源: Author Ignatius.L (Hdu 1061) 基准时间限制:1 秒 空间限制:131072 KB 分值: 5  难度:1级算法题 给出一...

3576
来自专栏owent

C++ 新特性学习(六) — 新的字符串编码和伪随机数

使用u””为能至少储存UTF-16的16位元编码,对应’\u’表示16位元的字符。

901

扫码关注云+社区

领取腾讯云代金券