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 }