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
",cas,ans);
57     }
58     return 0;
59 }
View Code
原文地址:https://www.cnblogs.com/-maybe/p/4389803.html