NC218219. 覆盖
描述
给出 n 条线段 ,q 次询问编号在 [a,b] 内的线段覆盖的总长度是多少。
线段覆盖的总长度定义为:在一条无限长的数轴上有多少整点,使得该整点至少被一条线段覆盖到。
输入描述
第一行两个整数 n,q;
接下来 n 行每行两个整数 ,表示一条线段;
接下来 q 行每行两个整数 a,b,表示询问的区间。
输出描述
q 行,每行一个整数,表示询问的答案。
示例1
输入:
4 3 7 9 1 6 6 10 3 7 1 2 3 3 4 4
输出:
9 5 5
C++(clang++11) 解法, 执行用时: 215ms, 内存消耗: 18948K, 提交时间: 2021-04-11 14:11:57
#include<cstdio> #include<vector> #include<set> #define lowbit(x) x&(-x) using namespace std; typedef pair<int,int> P; const int maxn=2e5+5; int n,m; int L[maxn],R[maxn],tr[maxn],ans[maxn]; vector<P>q[maxn]; set<P>s; void add(int x,int k){ while(x<=n){ tr[x]+=k; x+=lowbit(x); } } void upd(int l,int r,int k){ add(l,k);add(r+1,-k); } int query(int x){ int res=0; while(x){ res+=tr[x]; x-=lowbit(x); } return res; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d%d",&L[i],&R[i]); for(int i=1;i<=m;++i){ int x,y;scanf("%d%d",&x,&y); q[y].push_back((P){x,i}); } s.insert((P){1e9+1,0}); for(int i=1;i<=n;++i){ int l=L[i],r=R[i],fl=-1,l1=l-1; auto it=s.lower_bound((P){l-1,0}); while(1){ int x=it->first,y=it->second; int len=min(x,r)-l1; if(fl<0)fl=y; upd(y+1,i,len); if(x<=r){ l1=x; auto it1=it;++it;s.erase(it1); }else break; } if(l>1)s.insert((P){l-1,fl}); s.insert((P){r,i}); for(int j=0;j<q[i].size();++j) ans[q[i][j].second]=query(q[i][j].first); } for(int i=1;i<=m;++i) printf("%d\n",ans[i]); return 0; }