输入
佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值
可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你
,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
。注意:每种变化最多只有一个值发生变化。在样例输入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。所有数字均为正整数
,且小于等于100,000
Solution
首先想到n^2的DP,和n^2的LIS是一个道理
for(int i=1;i<=n;++i){
for(int j=1;j<i;++j){
if(maxv[j]<=a[i]&&a[j]<=minv[i]) dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
minv,maxv分别表示a[i]能变化的最小值和最大值
要求的满足这两个不等式的最大的dp值
其实就是一个二位数点问题,二维线段树就可以做
洛谷上轻松AC,BZOJ被MLE
然后改空间,手动二分数组大小
最后发现数组大小*108是AC的
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson o<<1,l,Mid
#define rson o<<1|1,Mid+1,r
#define MID Mid=(l+r)>>1
#define maxn 100010
int mx;
inline int read(){
int ret=0,ff=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') ff=-ff;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
ret=ret*10+ch-'0';
ch=getchar();
}
return ret*ff;
}
int maxv[maxn],minv[maxn],dp[maxn],a[maxn];
int siz=0;
int tr[maxn*108];
int ls[maxn*108],rs[maxn*108],rt[maxn<<2];
void insertY(int &o,int l,int r,int x,int val){
if(o==0) o=++siz;
if(l==r) tr[o]=max(tr[o],val);
else{
int MID;
if(x<=Mid) insertY(ls[o],l,Mid,x,val);
else insertY(rs[o],Mid+1,r,x,val);
tr[o]=max(tr[ls[o]],tr[rs[o]]);
}
return ;
}
void insertX(int o,int l,int r,int qx,int qy,int val){
insertY(rt[o],1,mx,qy,val);
if(l==r) return ;
int MID;
if(qx<=Mid) insertX(lson,qx,qy,val);
else insertX(rson,qx,qy,val);
}
int queryY(int o,int l,int r,int ql,int qr){
if(o==0) return 0;
if(ql<=l&&r<=qr) return tr[o];
int MID,ret=0;
if(ql<=Mid) ret=queryY(ls[o],l,Mid,ql,qr);
if(qr>Mid) ret=max(ret,queryY(rs[o],Mid+1,r,ql,qr));
return ret;
}
int queryX(int o,int l,int r,int xl,int xr,int yl,int yr){
if(xl<=l&&r<=xr) return queryY(rt[o],1,mx,yl,yr);
int MID,ret=0;
if(xl<=Mid) ret=queryX(lson,xl,xr,yl,yr);
if(xr>Mid) ret=max(ret,queryX(rson,xl,xr,yl,yr));
return ret;
}
int main(){
// freopen("bzoj4553.in","r",stdin);
int n=read(),m=read(),ans=0;
for(int i=1;i<=n;++i) maxv[i]=minv[i]=a[i]=read();
while(m--){
int x=read(),y=read();
maxv[x]=max(maxv[x],y);
mx=max(mx,maxv[x]);
minv[x]=min(minv[x],y);
}
for(int i=1;i<=n;++i){
dp[i]=queryX(1,1,mx,1,a[i],1,minv[i])+1;
insertX(1,1,mx,maxv[i],a[i],dp[i]);
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
return 0;
}