BZOJ 3126 Photo

Posted on 2017-02-14 11:15  ziliuziliu  阅读(169)  评论(0编辑  收藏  举报

好厉害啊这题。

详见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;
}