# [HEOI/TJOI2016]序列

## Hint:

$n \le 10^5$

## Solution:

$f[i]=f[j]+1$

$当max_j<val_i,val_j<min_i$

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=2e5+5,inf=1e9;
int n,m,cnt,f[mxn],tr[mxn],hd[mxn];

char c=getchar(); int x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(int &x,int y) {if(x<y) x=y;}
inline void chkmin(int &x,int y) {if(x>y) x=y;}

struct ed {
int to,nxt;
}t[mxn<<1];

inline void add(int u,int v) {
t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

struct Q {
int val,mx,mi,id;
}T[mxn];

int cmpv(Q x,Q y) {
return x.val<y.val;
}

int cmpm(Q x,Q y) {
return x.mx<y.mx;
}

int cmpi(Q x,Q y) {
return x.id<y.id;
}

void mod(int x,int y,int opt) {
while(x<=n) {
if(opt) chkmax(tr[x],y);
else tr[x]=-inf;
x+=(x&-x);
}
}

int query(int x) {
int res=-inf;
while(x) {
chkmax(res,tr[x]);
x-=(x&-x);
}
return res;
}

void cdq(int l,int r) {
if(l==r) return ;
int mid=(l+r)>>1;
cdq(l,mid);
sort(T+l,T+mid+1,cmpm);
sort(T+mid+1,T+r+1,cmpv);
int pos=l; //这里写错了几次
for(int i=mid+1;i<=r;++i) {
while(T[pos].mx<=T[i].val&&pos<=mid)
mod(T[pos].val,f[T[pos].id],1),++pos;
chkmax(f[T[i].id],query(T[i].mi)+1);
}
for(int i=l;i<pos;++i) mod(T[i].val,0,0);
sort(T+l,T+r+1,cmpi); //dp型cdq千万别忘记重排
cdq(mid+1,r);
}

int main()
{