poj2481 -- Cows 线段覆盖,树状数组处理
给定n个区间(l,r),问每个区间被多少个另外的区间所包含。
包含的定义(l1,r1),(l2,r2),如果l1<=l2<r2<=r1&&(l1,r1)!=(l2,r2),则(l1,r1)包含(l2,r2)。
用节点存储区间,然后给节点排序。l小的区间放在前面,l相同则r大的区间放在前面。
为什么这样排序呢?因为对排序之后的节点,节点n只可能被排在它前面的(0--n-1)号节点包含,而不可能被后面的包含。
那么(0--n-1)号节点中,又哪些能包含节点n呢?只要ri>=rn即可。(因为li<=ln的)。
至于那部分怎么统计,用树状数组可以达到lgn的效率。
View Code
1 //树状数组 2 //Accepted 2532K 1172MS C++ 1211B 3 #include <stdio.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <algorithm> 7 using namespace std; 8 #define MAX 200005 9 struct linee{ 10 int id,s,e; 11 }seq[MAX]; 12 13 int c[MAX],p[MAX]; 14 inline int lowbit(int a) { return a & (-a); } 15 16 void insert(int x,int d) 17 { 18 while(x <= 100005) 19 { 20 c[x] += d; 21 x += lowbit(x); 22 } 23 } 24 25 int getsum(int x) 26 { 27 int sum = 0; 28 while(x > 0) 29 { 30 sum += c[x]; 31 x -= lowbit(x); 32 } 33 return sum; 34 } 35 36 int cmp(linee a,linee b) 37 { 38 if(a.e!=b.e) 39 return a.e>b.e; 40 if(a.e==b.e&&a.s!=b.s) 41 return a.s<b.s; 42 } 43 44 int main(void) 45 { 46 int n,i; 47 while(scanf("%d",&n)!=EOF && n) 48 { 49 memset(c,0,sizeof(c)); 50 for(i=0;i<n;i++) 51 { 52 scanf("%d%d",&seq[i].s,&seq[i].e); 53 ++seq[i].s; 54 ++seq[i].e; 55 seq[i].id = i + 1; 56 p[i+1] = 0; 57 } 58 sort(seq,seq+n,cmp); 59 p[seq[0].id] = getsum(seq[0].s); 60 insert(seq[0].s,1); 61 for(i=1;i<n;i++) 62 { 63 if(seq[i].s == seq[i-1].s && seq[i].e == seq[i-1].e) 64 p[seq[i].id] = p[seq[i-1].id]; 65 else 66 p[seq[i].id] = getsum(seq[i].s); 67 insert(seq[i].s,1); 68 69 } 70 printf("%d",p[1]); 71 for(i=2;i<=n;i++) 72 { 73 74 printf(" %d",p[i]); 75 } 76 printf("\n"); 77 } 78 return 0; 79 }


浙公网安备 33010602011771号