Time Limit: 20 Sec
Memory Limit: 128 MB
Description
佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。玩具上有一个数列,数列中某些项的值
可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你
,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可
。注意:每种变化最多只有一个值发生变化。在样例输入1中,所有的变化是:
1 2 3
2 2 3
1 3 3
1 1 31 2 4
选择子序列为原序列,即在任意一种变化中均为不降子序列在样例输入2中,所有的变化是:3 3 33 2 3选择子序列
为第一个元素和第三个元素,或者第二个元素和第三个元素,均可满足要求
Input
输入的第一行有两个正整数n, m,分别表示序列的长度和变化的个数。接下来一行有n个数,表示这个数列原始的
状态。接下来m行,每行有2个数x, y,表示数列的第x项可以变化成y这个值。1 <= x <= n。所有数字均为正整数
,且小于等于100,000
Output
输出一个整数,表示对应的答案
题目分析
大匹方程是是老套路了,
d
p
[
i
]
dp[i]
dp[i]表示以
v
i
v_i
vi结尾的最长不下降子序列
d
p
[
i
]
=
m
a
x
(
d
p
[
j
]
)
+
1
(
j
≤
i
,
m
a
x
j
≤
v
i
,
v
j
≤
m
i
n
i
)
dp[i]=max(dp[j])+1\ (j\leq i,max_j\leq v_i,v_j\leq min_i)
dp[i]=max(dp[j])+1 (j≤i,maxj≤vi,vj≤mini)
观察这里的转移限制条件,不就是三维偏序嘛
CDQ分治优化DP即可
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long lt;
#define lowbit(x) ((x)&(-x))
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int inf=1e9;
const int maxn=100010;
int n,m;
struct node{int val,mi,mx,id,ans;}a[maxn],b[maxn];
int mx[maxn];
void update(int x,int v){ for(int i=x;i<=n;i+=lowbit(i))mx[i]=max(mx[i],v);}
int qmax(int x){ int res=0; for(int i=x;i>0;i-=lowbit(i))res=max(res,mx[i]); return res;}
void cls(int x){ for(int i=x;i<=n;i+=lowbit(i))mx[i]=0;}
bool cmp1(node x,node y){return x.mx<y.mx;}
bool cmp2(node x,node y){return x.val<y.val;}
bool cmp3(node x,node y){return x.id<y.id;}
void CDQ(int ll,int rr)
{
if(ll==rr) return;
int mid=ll+rr>>1;
CDQ(ll,mid);
sort(a+ll,a+mid+1,cmp1);
sort(a+mid+1,a+rr+1,cmp2);
int t1=ll,t2=mid+1;
while(t2<=rr)
{
while(a[t1].mx<=a[t2].val&&t1<=mid)
update(a[t1].val,a[t1].ans),t1++;
a[t2].ans=max(a[t2].ans,qmax(a[t2].mi)+1); t2++;
}
for(int i=ll;i<t1;++i)
cls(a[i].val);
sort(a+mid+1,a+rr+1,cmp3);
CDQ(mid+1,rr);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)
{
a[i].val=a[i].mi=a[i].mx=read();
a[i].id=i; a[i].ans=1;
}
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
a[x].mi=min(a[x].mi,y);
a[x].mx=max(a[x].mx,y);
}
CDQ(1,n); int ans=0;
for(int i=1;i<=n;++i)
ans=max(ans,a[i].ans);
printf("%d",ans);
return 0;
}