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