Bzoj4553: Tjoi2016&Heoi2016-序列

来源:互联网 发布:can总线通讯协议 编程 编辑:程序博客网 时间:2024/05/17 15:19

Description

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

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

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

3 3 3
3 2 3

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

Input

输入的第一行有两个正整数n, m
分别表示序列的长度和变化的个数。
接下来一行有n个数,表示这个数列原始的状态。
接下来m行,每行有2个数x, y,
表示数列的第x(1xn)项可以变化成y这个值
所有数字均为正整数,且小于等于105

Output

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

Sample Input

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

Sample Output

3

首先自然想到对于每一个位置
只有变化的最大值和最小值
对它造成影响
对于位置i,把它们分别记做MAXiMINi,i位置的值记做vi
考虑Dp

f[i]=max(f[j]+1)

0j<i,MAXjvi,vjMINi

可以用二维数据结构优化
也可以CDQ分治
考虑[l,mid][mid,r]的贡献
排一波序然后数据结构维护

#include <cstdio>#include <cstdlib>#include <cmath>#include <algorithm>#include <cstring>using namespace std;typedef long long ll;char ch;int fl;inline void read(int &a){    for(fl=1,ch=getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') fl=-fl;    for(a=0;ch>='0'&&ch<='9';ch=getchar()) a=(a<<3)+(a<<1)+(ch^'0');    a*=fl;}const int Maxn=1e5+10;struct Ques{    int x,y,id;    bool operator <(const Ques &A)const{return x!=A.x?x<A.x:id<A.id;} }G[Maxn]; int c[Maxn],MAXN[Maxn],MINN[Maxn],Val[Maxn],F[Maxn];inline void Add(int x,int v){for(int i=x;i<=Maxn;i+=i&(-i)) c[i]=max(c[i],v);}inline void Clear(int x){for(int i=x;i<=Maxn;i+=i&(-i)) c[i]=0;}inline int Qry(int x){ int Ans=0;for(int i=x;i;i-=i&(-i)) Ans=max(Ans,c[i]);return Ans;}void CDQ(int l,int r){    int mid=(l+r)>>1;    if(l==r){F[mid]=max(F[mid],1);return;}    CDQ(l,mid);    for(int i=l;i<=r;i++)G[i].id=i;    for(int i=l;i<=mid;i++)G[i].x=MAXN[i],G[i].y=Val[i];    for(int i=mid+1;i<=r;i++)G[i].x=Val[i],G[i].y=MINN[i];    sort(G+l,G+r+1);    for(int i=l;i<=r;i++){        if (G[i].id<=mid) Add(G[i].y,F[G[i].id]);        else F[G[i].id]=max(F[G[i].id],Qry(G[i].y)+1);    }    for(int i=l;i<=r;i++)    if (G[i].id<=mid)Clear(G[i].y);    CDQ(mid+1,r);}int main(){    int n,m,i,Ans=0,x,y;    read(n);read(m);    for(i=1;i<=n;i++)read(Val[i]),MAXN[i]=MINN[i]=Val[i];    for(i=1;i<=m;i++){        read(x);read(y);        MAXN[x]=max(MAXN[x],y);MINN[x]=min(MINN[x],y);    }    CDQ(1,n);    for(i=1;i<=n;i++)Ans=max(Ans,F[i]);    printf("%d",Ans);    return 0;}
原创粉丝点击