树状数组求逆序数的应用:
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 17874 | Accepted: 4819 | 
Description
Input
Output
Test case (case number): (number of crossings)
Sample Input
1 3 4 4 1 4 2 3 3 2 3 1
Sample Output
Test case 1: 5
题意很好理解,就是对v进行降序排列,然后求逆序数的个数就是交点的个数:
代码如下:
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<queue>
#include<map>
#include<ctype.h>
#define ll long long
#define loop1(k) for(int i=1;i<=k;i++)
#define loop2(k) for(int j=1;j<=k;j++)
#define pr(i) printf("%d\n",i);
using namespace std;
int n,m,k;
struct node{
int a;
int b;
}edge[1001000];
int cc[1001000];
bool cmp(node c,node d ){
if(c.a==d.a)
return c.b<d.b;
return c.a<d.a;
}
int low(int x){
return x&(-1*x);
}
int sum(int x){
 int num=0;
 while(x>=1){
 num+=cc[x];
 x-=low(x);
 }
 return num;
}
void update(int x)
{
 while(x<=m)
 {
 cc[x]++;
 x+=low(x);
 }
}
int main()
{
 int t;
 scanf("%d",&t);
 int ci=1;
 while(t--){
 memset(cc,0,sizeof(int)*m+15);
 scanf("%d%d%d",&n,&m,&k);
 memset(cc,0,sizeof(int)*m+15);
 for(int i=1;i<=k;i++)
 scanf("%d%d",&edge[i].a,&edge[i].b);
 sort(edge+1,edge+1+k,cmp);
 __int64 ans = 0;
 for(int i=1;i<=k;i++){
 update(edge[i].b);
 ans+=sum(m)-sum(edge[i].b);
 }
 printf("Test case %d: %I64d\n", ci, ans);
 ci++;
 }
 return 0;
}