首先容易想到那些覆蓋了其餘較小區間的區間是能夠忽略的··由於對於每一個詢問要儘可能多取區間···php
而後考慮對於每一個詢問···咱們確定會採起貪心策略,從詢問範圍的左端開始找··若是找到一個區間就取該區間··而後跳到該區間的右端··再繼續向右邊找下一個區間··這個方法確定是最優的····node
至於如何尋找,咱們考慮倍增(如今發現關於區間的一些查詢問題若是用數據結構解決不了的話基本上就是倍增了··),用g[i][j]表示從i點出發··在找到2^j個互不相交的區間後到達的最右端點··首先預處理g[i][0],而後再一次處理g[i][1],g[i][2]....便可ios
最後對於每一個詢問咱們像找lca那樣跳區間··邊跳邊更新答案就能夠了數據結構
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=2e5+5; inline int R(){ char c;int f=0; for(c=getchar();c<'0'||c>'9';c=getchar()); for(;c<='9'&&c>='0';c=getchar()) f=(f<<3)+(f<<1)+c-'0'; return f; } struct node{int l,r;}a[N],q[N],c[N]; int b[N*2],cnt,n,m,stack[N],top=0,bel[N*2],g[N*2][25]; inline void lsh(){ sort(b+1,b+cnt+1); cnt=unique(b+1,b+cnt+1)-b-1; for(int i=1;i<=n;i++){ a[i].l=lower_bound(b+1,b+cnt+1,a[i].l)-b; a[i].r=lower_bound(b+1,b+cnt+1,a[i].r)-b; } for(int i=1;i<=m;i++){ q[i].l=lower_bound(b+1,b+cnt+1,q[i].l)-b; q[i].r=lower_bound(b+1,b+cnt+1,q[i].r)-b; } } inline bool cmp(node a,node b){ if(a.l==b.l) return a.r>b.r; else return a.l<b.l; } inline void pre(){ sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++){ while(top&&a[i].l>=a[stack[top]].l&&a[i].r<=a[stack[top]].r) top--; stack[++top]=i; } n=0; for(int i=1;i<=top;i++) c[++n]=a[stack[i]]; int tail=1; for(int i=1;i<=n;i++){ while(tail<=c[i].l) g[tail][0]=c[i].r,tail++; } } inline int query(int l,int r){ int ans=0,i=l; for(int j=20;j>=0;j--) if(g[i][j]&&g[i][j]<=r) i=g[i][j],ans+=(1<<j); return ans; } int main(){ //freopen("a.in","r",stdin); while(scanf("%d%d",&n,&m)!=EOF){ top=cnt=0;memset(g,0,sizeof(g)); for(int i=1;i<=n;i++) a[i].l=R(),a[i].r=R(),b[++cnt]=a[i].l,b[++cnt]=a[i].r; for(int i=1;i<=m;i++) q[i].l=R(),q[i].r=R(),b[++cnt]=q[i].l,b[++cnt]=q[i].r; lsh();pre(); for(int i=1;i<=20;i++) for(int j=1;j<=cnt;j++) g[j][i]=g[g[j][i-1]][i-1]; for(int i=1;i<=m;i++) cout<<query(q[i].l,q[i].r)<<endl; } return 0; }