好厉害啊这题。
详见http://www.cnblogs.com/zig-zag/archive/2013/05/17/3083072.html
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 200500 #define inf 0x3f3f3f3f using namespace std; int n,m,lq,rq,lazy[maxn<<2],ls[maxn<<2],rs[maxn<<2],f[maxn],mx[maxn],tot=0,root,l[maxn],r[maxn]; int q[maxn],head=1,tail=0; void build(int &now,int left,int right) { now=++tot;lazy[now]=inf; if (left==right) return; int mid=(left+right)>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); } void modify(int now,int left,int right,int l,int r,int val) { if ((left==l) && (right==r)) { lazy[now]=min(lazy[now],val); return; } int mid=(left+right)>>1; if (r<=mid) modify(ls[now],left,mid,l,r,val); else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,val); else { modify(ls[now],left,mid,l,mid,val); modify(rs[now],mid+1,right,mid+1,r,val); } } int ask(int now,int left,int right,int pos) { if (left==right) return lazy[now]; int mid=(left+right)>>1; if (pos<=mid) return min(lazy[now],ask(ls[now],left,mid,pos)); else return min(lazy[now],ask(rs[now],mid+1,right,pos)); } int main() { scanf("%d%d",&n,&m);build(root,1,n); for (int i=1;i<=m;i++) { scanf("%d%d",&lq,&rq);mx[rq]=max(mx[rq],lq); modify(root,1,n,lq,rq,lq); } int now=0; for (int i=1;i<=n;i++) { int pos=ask(root,1,n,i); l[i]=now;r[i]=pos-1;if (pos==inf) r[i]=i-1; now=max(now,mx[i]); } int p=-1;l[n+1]=1;r[n+1]=n; for (int i=1;i<=n+1;i++) { while (p+1<=r[i]) { if (f[p+1]==-1) {p++;continue;} while (head<=tail && f[q[tail]]<f[p+1]) tail--; p++;q[++tail]=p; } while (head<=tail && q[head]<l[i]) head++; if (head<=tail) f[i]=f[q[head]]+(i!=n+1);else f[i]=-1; } printf("%d\n",f[n+1]); return 0; }