题目描述
Farmer John has decided to assemble a panoramic photo of a lineup of his N cows (1 <= N <= 200,000), which, as always, are conveniently numbered from 1..N. Accordingly, he snapped M (1 <= M <= 100,000) photos, each covering a contiguous range of cows: photo i contains cows a_i through b_i inclusive. The photos collectively may not necessarily cover every single cow. After taking his photos, FJ notices a very interesting phenomenon: each photo he took contains exactly one cow with spots! FJ was aware that he had some number of spotted cows in his herd, but he had never actually counted them. Based on his photos, please determine the maximum possible number of spotted cows that could exist in his herd. Output -1 if there is no possible assignment of spots to cows consistent with FJ"s photographic results.
给你一个n长度的数轴和m个区间,每个区间里有且仅有一个点,问能有多少个点
输入
* Line 1: Two integers N and M.
* Lines 2..M+1: Line i+1 contains a_i and b_i.
输出
* Line 1: The maximum possible number of spotted cows on FJ"s farm, or -1 if there is no possible solution.
样例输入
5 3
1 4
2 5
3 4
INPUT DETAILS: There are 5 cows and 3 photos. The first photo contains cows 1 through 4, etc.
样例输出
1
#include <cstdio>
#include <iostream>
#include <algorithm>
#define maxn 200005
#define maxx 100005
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{ char c=getchar();int x=0,y=1;
while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*y;
}
inline int m_min(int x,int y){return x<y?x:y;}
inline int m_max(int x,int y){return x>y?x:y;}
int n,m,head,tail,q[maxn],L[maxn],R[maxn],edg,f[maxn];
struct node
{ int x,y;
node(int a=0,int b=0):x(a),y(b){}
friend bool operator <(const node& a,const node& b){return a.y<b.y;}
}window[maxx];
void init()
{ int tmp=0x7fffffff;
for(int i=n,j=m;i>=1;--i)
{ while(j&&window[j].y>=i) tmp=m_min(tmp,window[j].x),--j;//寻找合法区间的右边界,注意右边的开闭
R[i]=tmp;//覆盖i的所有区间中最小的左端点.
}
tmp=0;
for(int i=1,j=1;i<=n;++i)
{ while(j<=m&&window[j].y<i) tmp=m_max(tmp,window[j].x),++j;//寻找合法区间的左边界
L[i]=tmp;//不覆盖i的区间中最大的左端点
}
R[edg]=n+1;
}
void dp()
{ head=1;tail=0;
for(int i=1,now=0;i<=edg;++i)//第n个可以不选,所以要dp到n+1来考虑n不选的情况.
{ //cout<<R[i]<<endl;
for(;now<i&&now<R[i];++now)
{ if(f[now]!=-1)
{ while(head<=tail&&f[q[tail]]<f[now]) --tail;
q[++tail]=now;
}
}
while(head<=tail&&q[head]<L[i]) ++head;
if(head<=tail) f[i]=f[q[head]]+(i!=edg);
else f[i]=-1;
}
}
int main()
{ n=read();m=read();int x,y;edg=n+1;
for(int i=1;i<=m;++i)
{ x=read();y=read();
window[i]=node(x,y);
}
sort(window+1,window+m+1);
init();dp();
printf("%d",f[edg]);
return 0;
}