4553: [Tjoi2016&Heoi2016]序列
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1330 Solved: 618
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
输出一个整数,表示对应的答案
Sample Input
3 4
1 2 3
1 2
2 3
2 1
3 4
Sample Output
3
思路:因为每次变换都是独立的,所以对于某2个数x和y来说,要使得x<y恒成立,即可以构成不降序列。
则有max(x)<=y且x<=min(y)。其中max(x)表示x的所有变换中的最大值,min同理。
那么这个问题就变成了求满足 i<j,且a[i]<=min(a[j]),max(a[i])<=a[j]的最长序列。
这样就是经典的三维偏序问题了。用cdq分治即可。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct lenka
{
int val,l,r,id;
}a[MAX];
int cmp1(const lenka& p,const lenka& q){return p.val<q.val;}
int cmp2(const lenka& p,const lenka& q){return p.l<q.l;}
int cmp3(const lenka& p,const lenka& q){return p.id<q.id;}
int n;
int d[MAX],A[MAX];
void add(int x,int y){while(x<=n){A[x]=max(A[x],y);x+=x&(-x);}}
int ask(int x){int ans=0;while(x){ans=max(ans,A[x]);x-=x&(-x);}return ans;}
void init(int x){while(x<=n){A[x]=0;x+=x&(-x);}}
void cdq(int L,int R)
{
if(L==R)return;
int m=(L+R)/2;
cdq(L,m);
sort(a+L,a+m+1,cmp1);
sort(a+m+1,a+R+1,cmp2);
int j=L;
for(int i=m+1;i<=R;i++)
{
while(j<=m&&a[j].val<=a[i].l)
{
add(a[j].r,d[a[j].id]);
j++;
}
d[a[i].id]=max(d[a[i].id],ask(a[i].val)+1);
}
for(int i=L;i<j;i++)init(a[i].r);
sort(a+m+1,a+R+1,cmp3);
cdq(m+1,R);
}
int main()
{
int m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].l=a[i].r=a[i].val;
a[i].id=i;
d[i]=1;
}
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x].l=min(a[x].l,y);
a[x].r=max(a[x].r,y);
}
cdq(1,n);
printf("%d\n",*max_element(d+1,d+n+1));
return 0;
}