题目链接:
POJ 3067 Japan
题意:
左列有n个点,右列有m给点。点的编号都是从1开始,然后有k条线段a–b,表示连接左列的a和右列的b,
问这些线段的交点一共有多少?保证交点处有且仅有两条线段相交。
分析:
按照对m端点编号降序排列,m端点编号相同对n端点编号降序排列。
从0到k遍历这些线段,树状数组中保存n端点信息,对于线段i只需要查询树状数组中n端点<=a[i]的线段个数。
跟上一道树状数组类似。
//2940K 391MS
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N=1010;
int T,n,m,k,cases=0;
long long bits[MAX_N];
struct Way{
int a,b;
bool operator <(const Way tmp) const{//优先按照b降序排列,其次按照a降排列
if(b==tmp.b) return a>tmp.a;
else return b>tmp.b;
}
}way[MAX_N*MAX_N];
inline void update(int x)
{
for(int i=x;i<MAX_N;i+=(i&(-i))){
bits[i]++;
}
}
inline long long sum(int x)
{
long long res=0;
for(int i=x-1;i>0;i-=(i&(-i))){
res+=bits[i];
}
return res;
}
int main()
{
//freopen("poj3067in.txt","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<k;i++){
scanf("%d%d",&way[i].a,&way[i].b);
}
sort(way,way+k);
memset(bits,0,sizeof(bits));
long long ans=0;
for(int i=0;i<k;i++){
ans+=sum(way[i].a);
update(way[i].a);
}
printf("Test case %d: %lld\n",++cases,ans);
}
return 0;
}