当前位置: 代码迷 >> 综合 >> YbtOJ NOIP2020 模拟赛 B 组 Day3 C.波动序列【dp】【线段树】
  详细解决方案

YbtOJ NOIP2020 模拟赛 B 组 Day3 C.波动序列【dp】【线段树】

热度:21   发布时间:2024-02-28 02:53:48.0

qwq

  • 题目:
  • 题意:
  • 分析:
  • 代码:


题目:

传送门


题意:

给出333个长度为nnn的序列,我们在这些序列的每一列选择一个或不选数,满足如下的条件::在这里插入图片描述
问这样我们能构造出的序列最长是多少


分析:

fi,j,k(k=0/1/2)f_{i,j,k}(k=0/1/2)fi,j,k?(k=0/1/2)表示当前选到第iii位,选出的最后一个数的大小为jjjk=0k=0k=0表示上一个数是1or21\ or\ 21 or 2序列的数,k=1k=1k=1表示的当前的单调性是递增的,k=2k=2k=2表示的当前的单调性是递减的
k=0k=0k=0的时候,我们只需保证和上个数的大小关系就可以转移过来
k=1/2k=1/2k=1/2的时候,我们看到序列的限制条件里的单调性是从sl?1s_{l-1}sl?1?开始的,所以第l?1l-1l?1的位置一定不是来自序列333的,故k=1k=1k=1不能从k=2k=2k=2转移来,k=2k=2k=2不能从k=1k=1k=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;
}