I can be used as a starting point to show that the opposite side can reach I from 1 and N.
Set Fl[i] means that from 1 to reach I need at least a few sides, fr[i] means to arrive from n I need to add at least a few sides.
Flip the graph up and down, from left to right in turn calculate fl[i], there is fl[i]=i-1-left Lis length, with a tree-like array maintenance can be $o (n\log N) $ to find out.
Calculate fr[i from right to left] likewise.
Then need to ask I,j (I<=J), make fr[i]+fl[j]<=k.
Since FL is monotonically increasing, FR is monotonically decreasing, so as I move right, J will move right, so you can $o (n) $.
#include <cstdio> #define N 100010int n,m,p,k,i,j,x,y,z,bit[n],fl[n],fr[n],pre,ans,cnt;struct e{int v,f; E*NXT;} *gl[n],*gr[n],pool[n],*cur=pool,*e;inline void Addl (int x,int y) {e=cur++;e->v=y;e->nxt=gl[x];gl[x]=e;} inline void addr (int x,int y) {e=cur++;e->v=y;e->nxt=gr[x];gr[x]=e;} inline void up (Int&a,int b) {if (a<b) a=b;} inline void Add (int x,int y) {for (; x<=m;x+=x&-x) up (bit[x],y);} inline int Ask (int x) {int t=0;for (; x;x-=x&-x) up (t,bit[x]); return t;} inline void Read (int&a) {char c;while (!) ( ((C=getchar ()) >= ' 0 ') && (c<= ' 9 ')); a=c-' 0 '; while (((C=getchar ()) >= ' 0 ') && (c<= ' 9 ')) (a*= Ten) +=c-' 0 ';} int main () {read (n), read (m), read (p), read (k); m++; while (p--) {read (x), read (y), read (z); y=m-y; Z?ADDL (x+1,y): Addr (x, y); } for (i=2;i<=n;i++) {to (E=GL[I];E;E=E->NXT) up (Pre,e->f=ask (e->v) +1); for (E=GL[I];E;E=E->NXT) Add (e->v,e->f); Fl[i]=i-1-pre; } for (pre=0,i=1;i<=m;i++) bit[i]=0; for (i=n-1;i;i--) {for (e=gr[I];E;E=E->NXT) Up (Pre,e->f=ask (e->v) +1); for (E=GR[I];E;E=E->NXT) Add (e->v,e->f); Fr[i]=n-i-pre; } for (i=j=1;i<=n;i++) {while (j<=n&&fr[i]+fl[j]<=k) j + +; Up (ans,j-i); if (!fl[i]&&!fr[i]) cnt++; } return printf ("%d", ans-cnt), 0;}
BZOJ1107: [POI2007] Driving test Egz