POJ3067 Japan 树状数组
Japan某城市的左边从上到下有n个城市,右边从上到下有m个城市,
现要建k条高铁,起点在左边,终点在右边,
问有多少个交点(任一交点只能有2条线同时经过)。
排序+树状数组,插点问段。
排序后,按起点从小到大扫一遍,
a[j] 表示前i条线中,终点为j的个数。
c[j] a[j]的树状数组。
注意:最后结果要用long long
1 #include<algorithm> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int MAXN=1000+5; 6 int c[MAXN]; 7 struct Edge 8 { 9 int u,v; 10 }edge[MAXN*MAXN]; 11 int n,m; 12 bool cmp(Edge i,Edge j) 13 { 14 if(i.u==j.u) 15 return i.v<j.v; 16 return i.u<j.u; 17 } 18 int lowbit(int x) 19 { 20 return x&(-x); 21 } 22 int sum(int x) 23 { 24 int temp=0; 25 while(x>0){ 26 temp+=c[x]; 27 x-=lowbit(x); 28 } 29 return temp; 30 } 31 void update(int x,int num) 32 { 33 while(x<=m){ 34 c[x]+=num; 35 x+=lowbit(x); 36 } 37 } 38 int main() 39 { 40 int test; 41 int cas=0; 42 scanf("%d",&test); 43 while(test--){ 44 cas++; 45 int k; 46 scanf("%d%d%d",&n,&m,&k); 47 for(int i=1;i<=k;i++) 48 scanf("%d%d",&edge[i].u,&edge[i].v); 49 sort(edge+1,edge+k+1,cmp); 50 memset(c,0,sizeof(c)); 51 long long ans=0; 52 for(int i=1;i<=k;i++){ 53 update(edge[i].v,1); 54 ans+=(long long)(i-sum(edge[i].v)); 55 } 56 printf("Test case %d: %I64d\n",cas,ans); 57 } 58 return 0; 59 }