题目:
题意:
给出
3
3
3个长度为
n
n
n的序列,我们在这些序列的每一列选择一个或不选数,满足如下的条件
:
:
:
问这样我们能构造出的序列最长是多少
分析:
设
f
i
,
j
,
k
(
k
=
0
/
1
/
2
)
f_{i,j,k}(k=0/1/2)
fi,j,k(k=0/1/2)表示当前选到第
i
i
i位,选出的最后一个数的大小为
j
j
j,
k
=
0
k=0
k=0表示上一个数是
1
o
r
2
1\ or\ 2
1 or 2序列的数,
k
=
1
k=1
k=1表示的当前的单调性是递增的,
k
=
2
k=2
k=2表示的当前的单调性是递减的
当
k
=
0
k=0
k=0的时候,我们只需保证和上个数的大小关系就可以转移过来
当
k
=
1
/
2
k=1/2
k=1/2的时候,我们看到序列的限制条件里的单调性是从
s
l
−
1
s_{l-1}
sl−1开始的,所以第
l
−
1
l-1
l−1的位置一定不是来自序列
3
3
3的,故
k
=
1
k=1
k=1不能从
k
=
2
k=2
k=2转移来,
k
=
2
k=2
k=2不能从
k
=
1
k=1
k=1转移来
我们发现我们转移的时候可以通过线段树来找到上一个位置在哪里,进而转移
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
inline LL read()
{
LL s=0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {s=s*10+c-'0';c=getchar();}
return s*f;
}
struct tree{
int w[400005];
void change(int k,int L,int R,int pos,int val)
{
if(L==R) {w[k]=max(w[k],val);return;}
int mid=(L+R)>>1;
if(pos<=mid) change(k*2,L,mid,pos,val);
else change(k*2+1,mid+1,R,pos,val);
w[k]=max(w[k*2],w[k*2+1]);
}
int ask(int k,int L,int R,int l,int r)
{
if(L==l&&R==r) return w[k];
int mid=(L+R)>>1;
if(r<=mid) return ask(k*2,L,mid,l,r);
if(l>mid) return ask(k*2+1,mid+1,R,l,r);
return max(ask(k*2,L,mid,l,mid),ask(k*2+1,mid+1,R,mid+1,r));
}
}t,tup,tdown;
int a[100005],b[100005],c[100005],ls[300005];
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int n=read(),len=0;
for(int i=1;i<=n;i++) ls[++len]=a[i]=read();
for(int i=1;i<=n;i++) ls[++len]=b[i]=read();
for(int i=1;i<=n;i++) ls[++len]=c[i]=read();
sort(ls+1,ls+1+len);
len=unique(ls+1,ls+1+len)-ls-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(ls+1,ls+1+len,a[i])-ls;
b[i]=lower_bound(ls+1,ls+1+len,b[i])-ls;
c[i]=lower_bound(ls+1,ls+1+len,c[i])-ls;
}
for(int i=1;i<=n;i++)
{
int fa=max(t.ask(1,1,len,1,a[i]),max(tdown.ask(1,1,len,1,a[i]),tup.ask(1,1,len,1,a[i])))+1;
int fb=max(t.ask(1,1,len,b[i],len),max(tdown.ask(1,1,len,b[i],len),tup.ask(1,1,len,b[i],len)))+1;
int fcup=max(t.ask(1,1,len,1,c[i]),tup.ask(1,1,len,1,c[i]))+1;
int fcdown=max(t.ask(1,1,len,c[i],len),tdown.ask(1,1,len,c[i],len))+1;
t.change(1,1,len,a[i],fa); t.change(1,1,len,b[i],fb);
tup.change(1,1,len,c[i],fcup);
tdown.change(1,1,len,c[i],fcdown);
}
cout<<max(t.w[1],max(tup.w[1],tdown.w[1]));
return 0;
}