poj3067 Japan 树状数组求逆序对

题目链接:http://poj.org/problem?id=3067

题目就是让我们求连线后交点的个数

很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序

那么答案即为逆序对的个数

用树状数组求解逆序对

代码:

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 #define maxn 1010
 8 int n,m,k;
 9 int c[maxn*maxn];
10 long long int  ans;
11 class point
12 {
13    public:
14    int s,e;
15 };
16 point P[maxn*maxn];
17 int lowbit(int x)
18 {
19     return x&(-x);
20 }
21 void add(int i,int val)
22 {
23    while(i<=m)
24    {
25         c[i]+=val;
26         i+=lowbit(i);
27    }
28 }
29 int sum(int i)
30 {
31      int s=0;
32      while(i>0)
33      {
34          s+=c[i];
35          i-=lowbit(i);
36      }
37      return s;
38 }
39 bool cmp(point a ,point b)
40 {
41    if(a.s!=b.s) return a.s <b.s;
42    else return a.e<b.e;
43 }
44 int main()
45 {
46     int t;
47     scanf("%d",&t);
48     int iCase=1;
49     while(t--)
50     {
51        scanf("%d%d%d",&n,&m,&k);
52        m=max(n,m);
53        memset(c,0,sizeof(c));
54 
55        for(int i=1;i<=k;i++)
56           scanf("%d%d",&P[i].s,&P[i].e);
57        sort(P+1,P+1+k,cmp);
58        ans=0;
59        add(P[1].e,1);
60 
61        for(int i=2;i<=k;i++)
62          {
63            ans+=i-1-sum(P[i].e);
64            add(P[i].e,1);
65          }
66 
67        cout<<"Test case "<<iCase++<<": "<<ans<<endl;
68 
69     }
70     return 0;
71 }

 

posted on 2013-10-04 13:47  GyyZyp  阅读(138)  评论(0编辑  收藏  举报

导航