题目链接:http://poj.org/problem?id=3067
题目就是让我们求连线后交点的个数
很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序
那么答案即为逆序对的个数
用树状数组求解逆序对
代码:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1010
int n,m,k;
int c[maxn*maxn];
long long int ans;
class point
{
public:
int s,e;
};
point P[maxn*maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int i,int val)
{
while(i<=m)
{
c[i]+=val;
i+=lowbit(i);
}
}
int sum(int i)
{
int s=;
while(i>)
{
s+=c[i];
i-=lowbit(i);
}
return s;
}
bool cmp(point a ,point b)
{
if(a.s!=b.s) return a.s <b.s;
else return a.e<b.e;
}
int main()
{
int t;
scanf("%d",&t);
int iCase=;
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
m=max(n,m);
memset(c,,sizeof(c)); for(int i=;i<=k;i++)
scanf("%d%d",&P[i].s,&P[i].e);
sort(P+,P++k,cmp);
ans=;
add(P[].e,); for(int i=;i<=k;i++)
{
ans+=i--sum(P[i].e);
add(P[i].e,);
} cout<<"Test case "<<iCase++<<": "<<ans<<endl; }
return ;
}