C. Covered Points Count
题意
给N条线段,这些线段可以覆盖至少一个点,求被1~N条线段覆盖的点各有多少个?
input
3 0 3 1 3 3 8
output
6 2 1
样例解释
分析
开始为一条高度为0直线,对于每一条线段[l,r],我们就让位于[l,r]部分高度-1,处理完之后,某个点下降了多少高度就是被多少条线段所覆盖。
从这里就已经可以看出来是一个典型的差分题,让位于[l,r]部分高度-1,就是差分数组B[l]-=1
,B[r+1]+=1
, 处理完之后再还原成原始高度数组即可。但是此题还涉及了离散化,所以不能一个点一个点的算,而需要按线段来算(其实就是离散化还原)
代码
#include <iostream> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int maxn = 1e6+10; int N; ll pos[maxn][2]; ll cnt[maxn],B[maxn]; vector<ll> ve; int ind(ll x){ //离散定位 int idx = lower_bound(ve.begin(),ve.end(),x)-ve.begin(); return idx; } int main(){ cin>>N; ll a,b; for(int i = 0;i<N;i++){ scanf("%lld %lld",&a,&b); if(a>b) swap(a,b); pos[i][0] = a,pos[i][1] = b+1; ve.push_back(a); ve.push_back(b+1); } sort(ve.begin(),ve.end()); ve.erase(unique(ve.begin(),ve.end()),ve.end()); for(int i = 0;i<N;i++){ a = pos[i][0],b = pos[i][1]; int id1 = ind(a),id2 = ind(b); B[id1]-=1; B[id2]+=1; } for(int i = 0;i<ve.size()-1;i++){ if(i) B[i] = B[i-1]+B[i]; cnt[abs(B[i])] += ve[i+1]-ve[i];//B[i]下降高度 } for(int i = 1;i<=N;i++) printf("%lld ",cnt[i]); return 0; }