树状数组求逆序数的应用:
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;
}