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 }
View Code

 

你可能感兴趣的:(树状数组)