题目:
题意:
给出 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;
}