Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16732 | Accepted: 4488 |
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
Source
其计算逆序数的过程是这么一个过程。
1>,输入5, 调用upDate(5, 1),把第5位设置为1
1 2 3 4 5
0 0 0 0 1
计算1-5上比5小的数字存在么?这里用到了树状数组的getSum(5) = 1操作,
现在用输入的下标1 - getSum(5) =0就可以得到对于5的逆序数为0。
2>. 输入2,调用upDate(2, 1),把第2位设置为1
1 2 3 4 5
0 1 0 0 1
计算1-2上比2小的数字存在么?这里用到了树状数组的getSum(2) = 1操作,
现在用输入的下标2 - getSum(2) =1就可以得到对于2的逆序数为1。
3>. 输入1,调用upDate(1, 1),把第1位设置为1
1 2 3 4 5
1 1 0 0 1
计算1-1上比1小的数字存在么?这里用到了树状数组的getSum(1) = 1操作,
现在用输入的下标 3 - getSum(1) =2就可以得到对于1的逆序数为2。
4.> 输入4,调用upDate(4, 1),把第5位设置为1
1 2 3 4 5
1 1 0 1 1
计算1-4上比4小的数字存在么?这里用到了树状数组的getSum(4) = 3操作,
现在用输入的下标4 - getSum(4) =1就可以得到对于4的逆序数为1。
5>. 输入3,调用upDate(3, 1),把第3位设置为1
1 2 3 4 5
1 1 1 1 1
计算1-3上比3小的数字存在么?这里用到了树状数组的getSum(3) = 3操作,
现在用输入的下标5 - getSum(3) =2就可以得到对于3的逆序数为2。
6>. 0+1+2+1+2 = 6 这就是最后的逆序数。。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#define MN 1005*1005
using namespace std;
int c[MN],N,K,M;
class A
{
public:
int x,y;
}a[MN];
int lowbit(int x)//计算树状数组中c数组是几个数字的和?
{
return x & (-x);
}
long long get_sum(int x)//求得和值
{
long long sum = 0,i;
for(i = x;i > 0;i -= lowbit(i))
sum += c[i];
return sum;
}
void update(int x,int value)//更新值
{
int i;
for(i = x;i <= M ;i+=lowbit(i))
c[i]+=value;
}
bool cmp(A a,A b)
{
if(a.x == b.x)
{
return a.y<b.y;
}
else if(a.x != b.x)
return a.x<b.x;
}
int main()
{
int T,i,j,k;
long long ans;
scanf("%d",&T);
for( i = 0;i<T;i++)
{
scanf("%d %d %d",&N,&M,&K);
memset(a,0,sizeof(a));
for(j = 0;j < K;j++)
{
scanf("%d %d",&a[j].x,&a[j].y);
}
sort(a,a+K,cmp);
memset(c,0,sizeof(c));
ans = 0;
for(j = 0;j < K;j++)
{
update(a[j].y,1);//求逆序数。
ans += (get_sum(M)-get_sum(j));
}
printf("Test case %d: %I64d\n",i+1,ans);
}
return 0;
}
好的,就这些。