codeforces 1000C - Covered Points Count 【差分】
题目:戳这里
题意:给出n个线段,问被1~n个线段覆盖的点分别有多少。
解题思路:
这题很容易想到排序后维护每个端点被覆盖的线段数,关键是端点值不好处理。比较好的做法是用差分的思想,把闭区间的线段改为前闭后开,同时在求总点数的时候,也按前闭后开的区间来求,这样就巧妙避开了两个端点之间的讨论,只用维护好一个端点就行了。
代码比文字更容易理解:
1 #include <bits/stdc++.h> 2 #define lowbit(x) x&-x; 3 typedef long long ll; 4 const int maxn = 4e5+10; 5 const int inf = 0x3f3f3f3f; 6 const ll mod = 998244353; 7 using namespace std; 8 ll n; 9 struct nod { 10 ll x; 11 int f; 12 }co[maxn]; 13 ll cnt[maxn]; 14 bool cmp(nod a, nod b) { 15 if(a.x == b.x) return a.f > b.f; 16 return a.x < b.x; 17 } 18 int main(){ 19 ll l,r; 20 scanf("%lld", &n); 21 for(ll i = 0ll; i < n; ++i) { 22 l=2ll*i+1ll; r=2ll*i+2ll; 23 scanf("%lld %lld", &co[l].x, &co[r].x); 24 co[r].x++;//转换为前闭后开 25 co[l].f = 1; 26 co[r].f = -1; 27 } 28 int now = 1; 29 sort(co + 1, co + 1 + 2*n, cmp); 30 for(ll i = 2ll; i <= 2ll * n; ++i) { 31 cnt[now] += co[i].x - co[i-1].x; 32 now += co[i].f; 33 } 34 for(ll i = 1; i <= n; ++i) { 35 printf("%lld ", cnt[i]); 36 } 37 return 0; 38 }