考察线段树的区间最小和单点修改.因为树状数组还没学完,所以还是用线段树来写..其实线段树还没系统的学...但是这种题只是个模板而已.
考虑我到了第i个,我包含的区间是(s[i],t[i]).这里面的区间都是可取的,我要做的就是问这个区间的最小值在哪里,然后我假如找到了这个区间的最小值,那么我只要更新右端点即可,因为下次询问假如它是要用这个区间,那么肯定是包含这个区间的右端点的,如此这个题就完美的解决了.
代码如下:
#include <stdio.h>
const int N=2e6+4;
int s[N],t[N],tmin[N];
int min(int a,int b)
{
if(a<b) return a;
else return b;
}
int query(int u,int L,int R,int l,int r)//从第u个节点开始,在区间L,R范围内查询l,r的min
{
if(R<l||L>r) return 2e9;
if(L>=l&&R<=r) return tmin[u];
int mid=(L+R)>>1;
return min(query(u<<1,L,mid,l,r),query(u<<1|1,mid+1,R,l,r));
}
void modify(int u,int L,int R,int pos,int val)
{
if(L==R) {tmin[u]=min(tmin[u],val);return;}
int mid=(L+R)>>1;
if(pos<=mid) modify(u<<1,L,mid,pos,val);
else modify(u<<1|1,mid+1,R,pos,val);
tmin[u]=min(tmin[u<<1],tmin[u<<1|1]);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&s[i],&t[i]);
for(int i=1;i<=4*n;i++) tmin[i]=2e9;
modify(1,1,n,1,0);
for(int i=1;i<=m;i++)
{
int cnt=query(1,1,n,s[i],t[i]);
modify(1,1,n,t[i],cnt+1);
}
printf("%d\n",query(1,1,n,n,n));
return 0;
}

京公网安备 11010502036488号