cjb-poi2010monotonicity
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <cassert>
#define pb push_back
#define mp make_pair
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
#define N 510000
int n,k;
int f[N],pre[N],a[N];
char s[N];
struct SegmentTree
{
int p[3*N],l[3*N],r[3*N],tot;
int newnode()
{
tot++; l[tot]=r[tot]=p[tot]=0; return tot;
}
void init()
{
tot=-1; newnode(); newnode();
}
void insert(int t,int ll,int rr,int k,int pos)
{
if (ll==rr)
{
if (f[p[t]]<f[pos])p[t]=pos;
return;
}
int mid=(ll+rr)/2;
if (k<=mid)
{
if (l[t]==0)l[t]=newnode();
insert(l[t],ll,mid,k,pos);
}
else
{
if (r[t]==0)r[t]=newnode();
insert(r[t],mid+1,rr,k,pos);
}
if (f[p[l[t]]]>f[p[r[t]]])p[t]=p[l[t]]; else p[t]=p[r[t]];
}
int get(int t,int ll,int rr,int a,int b)
{
if (t==0 || a>b)return 0;
if (a<=ll && rr<=b)return p[t];
int mid=(ll+rr)/2;
int t1=0,t2=0;
if (a<=mid)t1=get(l[t],ll,mid,a,b);
if (b>mid)t2=get(r[t],mid+1,rr,a,b);
if (f[t1]>f[t2])return t1; else return t2;
}
}A,B,C;
int main()
{
cin>>n>>k;
rep(i,n)scanf("%d",&a[i]);
rep(i,k){ char ts[5]; scanf("%s",ts); s[i]=ts[0]; }
A.init(); B.init(); C.init();
rep(i,n)
{
f[i]=1; pre[i]=0;
int p1=A.get(1,1,1000001,1,a[i]-1);
if (p1 && f[p1]+1>f[i])f[i]=f[p1]+1,pre[i]=p1;
int p2=B.get(1,1,1000001,a[i],a[i]);
if (p2 && f[p2]+1>f[i])f[i]=f[p2]+1,pre[i]=p2;
int p3=C.get(1,1,1000001,a[i]+1,1000001);
if (p3 && f[p3]+1>f[i])f[i]=f[p3]+1,pre[i]=p3;
char c=s[(f[i]-1)%k + 1];
if (c=='<')A.insert(1,1,1000001,a[i],i);
if (c=='=')B.insert(1,1,1000001,a[i],i);
if (c=='>')C.insert(1,1,1000001,a[i],i);
}
int maxp=1;
rep(i,n)if (f[i]>f[maxp])maxp=i;
static vector<int> ans; ans.clear();
for(int now=maxp;now;now=pre[now])ans.pb(a[now]);
reverse(ans.begin(),ans.end());
cout<<f[maxp]<<endl;
for(int i=0;i<f[maxp];i++)printf("%d%c",ans[i],i==f[maxp]-1?'\n':' ');
return 0;
}
}}}
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <cassert>
#define pb push_back
#define mp make_pair
#define rep(i,n) for(int i=1;i<=n;i++)
using namespace std;
#define N 510000
int n,k;
int f[N],pre[N],a[N];
char s[N];
struct SegmentTree
{
int p[3*N],l[3*N],r[3*N],tot;
int newnode()
{
tot++; l[tot]=r[tot]=p[tot]=0; return tot;
}
void init()
{
tot=-1; newnode(); newnode();
}
void insert(int t,int ll,int rr,int k,int pos)
{
if (ll==rr)
{
if (f[p[t]]<f[pos])p[t]=pos;
return;
}
int mid=(ll+rr)/2;
if (k<=mid)
{
if (l[t]==0)l[t]=newnode();
insert(l[t],ll,mid,k,pos);
}
else
{
if (r[t]==0)r[t]=newnode();
insert(r[t],mid+1,rr,k,pos);
}
if (f[p[l[t]]]>f[p[r[t]]])p[t]=p[l[t]]; else p[t]=p[r[t]];
}
int get(int t,int ll,int rr,int a,int b)
{
if (t==0 || a>b)return 0;
if (a<=ll && rr<=b)return p[t];
int mid=(ll+rr)/2;
int t1=0,t2=0;
if (a<=mid)t1=get(l[t],ll,mid,a,b);
if (b>mid)t2=get(r[t],mid+1,rr,a,b);
if (f[t1]>f[t2])return t1; else return t2;
}
}A,B,C;
int main()
{
cin>>n>>k;
rep(i,n)scanf("%d",&a[i]);
rep(i,k){ char ts[5]; scanf("%s",ts); s[i]=ts[0]; }
A.init(); B.init(); C.init();
rep(i,n)
{
f[i]=1; pre[i]=0;
int p1=A.get(1,1,1000001,1,a[i]-1);
if (p1 && f[p1]+1>f[i])f[i]=f[p1]+1,pre[i]=p1;
int p2=B.get(1,1,1000001,a[i],a[i]);
if (p2 && f[p2]+1>f[i])f[i]=f[p2]+1,pre[i]=p2;
int p3=C.get(1,1,1000001,a[i]+1,1000001);
if (p3 && f[p3]+1>f[i])f[i]=f[p3]+1,pre[i]=p3;
char c=s[(f[i]-1)%k + 1];
if (c=='<')A.insert(1,1,1000001,a[i],i);
if (c=='=')B.insert(1,1,1000001,a[i],i);
if (c=='>')C.insert(1,1,1000001,a[i],i);
}
int maxp=1;
rep(i,n)if (f[i]>f[maxp])maxp=i;
static vector<int> ans; ans.clear();
for(int now=maxp;now;now=pre[now])ans.pb(a[now]);
reverse(ans.begin(),ans.end());
cout<<f[maxp]<<endl;
for(int i=0;i<f[maxp];i++)printf("%d%c",ans[i],i==f[maxp]-1?'\n':' ');
return 0;
}