题意:
输入若干个区间,对于一个区间(a,b),如果存在一个区间(x,y)满足x <= a && y >= b && y - x > b - a,那么就说(x,y)比(a,b)大。
求比每一个区间大的区间有多少。
思路:
树状数组,这题最关键的其实是有重复的区间。
首先把区间按照起点升序排序,如果起点相同,那么按照终点降序排序,这样的目的是为了先统计大区间。
对于一个区间,如果这个区间和前面的区间重合,那么它的答案就是前一个区间的答案;
若不重合,那么统计大于等于这个区间的终点的区间的个数,就是答案。
为什么,因为前面的区间的起点大于等于它,并且终点大于等于它,并且不存在起点和终点都等于它的区间,因为重复的区间已经特殊处理了。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 const int N = 1e5 + 10; 6 int len[N]; 7 struct node 8 { 9 int id; 10 int s,e; 11 } a[N]; 12 int mlen; 13 int gg[N]; 14 bool cmp(node aa,node bb) 15 { 16 if (aa.s == bb.s) return aa.e > bb.e; 17 return aa.s < bb.s; 18 } 19 int lowbit(int x) 20 { 21 return x&(-x); 22 } 23 void add(int x) 24 { 25 for (int i = x;i <= mlen;i += lowbit(i)) len[i] += 1; 26 } 27 int getsum(int x) 28 { 29 int ans = 0; 30 for (int i = x;i > 0;i -= lowbit(i)) ans += len[i]; 31 return ans; 32 } 33 int main() 34 { 35 int n; 36 while (scanf("%d",&n) != EOF && n) 37 { 38 mlen = 0; 39 memset(len,0,sizeof(len)); 40 memset(gg,0,sizeof(gg)); 41 for (int i = 0;i < n;i++) 42 { 43 int x,y; 44 scanf("%d%d",&x,&y); 45 x++,y++; 46 a[i].id = i; 47 a[i].s = x; 48 a[i].e = y; 49 mlen = max(y,mlen); 50 } 51 sort(a,a+n,cmp); 52 for (int i = 0;i < n;i++) 53 { 54 int x = a[i].s,y = a[i].e; 55 if (i > 0 && x == a[i-1].s && y == a[i-1].e) 56 { 57 gg[a[i].id] = gg[a[i-1].id]; 58 add(y); 59 continue; 60 } 61 int tmp = getsum(y-1); 62 tmp = i - tmp; 63 gg[a[i].id] = tmp; 64 add(y); 65 } 66 for (int i = 0;i < n;i++) 67 { 68 printf("%d%c",gg[i],i == n - 1 ? ' ':' '); 69 } 70 } 71 return 0; 72 }