洛谷P4093 [HEOI2016/TJOI2016]序列

2018-02-11 by 自为风月马前卒

题目描述

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

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

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

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

3 3 33 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]$ && $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;}

第七城市

栏目导航(关闭)