标签:
题目链接:http://codeforces.com/problemset/problem/652/D
大意:给若干个线段,保证线段端点不重合,问每个线段内部包含了多少个线段。
方法是对所有线段的端点值离散化,按照左端点从大到小排序,顺着这个顺序处理所有线段,那么满足在它内部的线段一定是之前已经扫到过的。用树状数组判断有多少是在右端点范围内。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <math.h> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <ctime> 12 #include <set> 13 using namespace std; 14 15 const int N=4e5+10; 16 int a[N]; 17 int b[N]; 18 int lowbit(int x) { 19 return x&(-x); 20 } 21 int get(int x) { 22 int ret=0; 23 while (x) { 24 ret+=a[x]; 25 x-=lowbit(x); 26 } 27 return ret; 28 } 29 void add(int x,int add) { 30 while (x<N) { 31 a[x]+=add; 32 x+=lowbit(x); 33 } 34 } 35 struct Seg{ 36 int l,r; 37 int id; 38 39 Seg() { } 40 41 Seg(int l, int r, int id) : l(l), r(r), id(id) { } 42 bool operator < (const Seg & o) const { 43 return l>o.l; 44 } 45 }seg[N]; 46 int ans[N]; 47 int main () { 48 int n; 49 scanf("%d",&n); 50 int t=0; 51 for (int i=1;i<=n;i++) { 52 scanf("%d %d",&seg[i].l,&seg[i].r); 53 b[t++]=seg[i].l; 54 b[t++]=seg[i].r; 55 seg[i].id=i; 56 } 57 sort(b,b+t); 58 int k=unique(b,b+t)-b; 59 for (int i=1;i<=n;i++) { 60 seg[i].l=lower_bound(b,b+t,seg[i].l)-b+1; 61 seg[i].r=lower_bound(b,b + t,seg[i].r)-b+1; 62 } 63 sort(seg+1,seg+1+n); 64 for (int i=1;i<=n;i++) { 65 int id=seg[i].id; 66 ans[id]=get(seg[i].r); 67 add(seg[i].r,1); 68 } 69 for (int i=1;i<=n;i++) { 70 printf("%d\n",ans[i]); 71 } 72 return 0; 73 }
CF Educational Codeforces Round 10 D. Nested Segments 离散化+树状数组
标签:
原文地址:http://www.cnblogs.com/micrari/p/5394883.html