POJ 2376 Cleaning Shifts

二分+RMQ过的这题估计也只有我了吧。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn=250000+10;
int n,T;
int a[4*maxn];
int maxl[maxn][16];
struct X
{
    int L,R;
} s[maxn];

int MAX(int a,int b)
{
    if(a>b) return a;
    return b;
}

void S_table()
{
    int l = int(log((double)n)/log(2.0));
    for (int j=1; j<=l; j++)
        for (int i=1; i + (1 << (j-1) ) - 1 <=n; ++i)
            maxl[i][j] = MAX(maxl[i][j-1], maxl[i + (1 << (j-1) )][j-1]);
}

int rmq(int l, int r)
{
    int k = int(log((double)(r-l+1))/log(2.0));
    int a1 = MAX(maxl[l][k], maxl[r - (1<<k) + 1][k]);
    return a1;
}

int main()
{
    while(~scanf("%d%d",&n,&T))
    {
        memset(a,0,sizeof a);
        for(int i=1; i<=n; i++)
        {
            int x,y; scanf("%d%d",&x,&y);
            a[x]=MAX(a[x],y);
        }

        int n=0;
        for(int i=1; i<=T; i++)
        {
            if(a[i]==0) continue;
            n++; s[n].L=i; s[n].R=a[i];
        }

        for(int i=0; i<=n; i++) maxl[i][0] = s[i].R;
        S_table();

        int ans=1;
        if(a[1]==0) printf("-1\n");
        else if(a[1]>=T) printf("1\n");
        else
        {
            int pre=a[1];
            while(1)
            {
                pre=pre+1;
                int left=1,right=n,pos=-1;
                while(left<=right)
                {
                    int mid=(left+right)/2;
                    if(s[mid].L<=pre) pos=mid,left=mid+1;
                    else if(s[mid].L>pre) right=mid-1;
                }
                if(pos==-1){ans=-1;break;}
                int M=rmq(1,pos);
                if(M<pre){ans=-1;break;}
                else { ans++;pre=M; if(M>=T) break; }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

posted @ 2016-03-27 10:54  Fighting_Heart  阅读(176)  评论(0编辑  收藏  举报