题意:
左侧有一列点..从上到下1~N..右侧有一列点..从上到下1~M...现在告诉左右侧哪两点有边..问一共有多少个交点...
题解:
可以发现一个交点出现..仅当这两个线段头尾的头尾的大小相反...比如(1,2)和(2,1)相交..因为i1比2小..后有2比1大..
所以把所有线段按第一个数从大到小排序.然后找逆序数就是...统计逆序数用树状数组解决..注意的是线段的总数可能到达1000*1000=10^6...
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<time.h>
#define ll long long
#define oo 1000000009
#define MAXN 1000005
#define pi acos(-1.0)
#define esp 1e-30
#define MAXD 4
using namespace std;
struct node
{
ll x,y;
}L[MAXN<<6];
int M;
ll sum[MAXN+2];
bool cmp(node a,node b)
{
if (a.x!=b.x) return a.x>b.x;
return a.y>b.y;
}
void update(ll x,int k)
{
while (k<=M)
{
sum[k]+=x;
k+=k&(-k);
}
}
ll query(int k)
{
ll ans=0;
while (k)
{
ans+=sum[k];
k-=k&(-k);
}
return ans;
}
int main()
{
int T,N,K,cases,i;
ll ans;
scanf("%d",&T);
for (cases=1;cases<=T;cases++)
{
scanf("%d%d%d",&N,&M,&K);
for (i=1;i<=K;i++) scanf("%I64d%I64d",&L[i].x,&L[i].y);
sort(L+1,L+1+K,cmp);
memset(sum,0,sizeof(sum)),ans=0;
for (i=1;i<=K;i++)
ans+=query(L[i].y-1),update(1,L[i].y);
printf("Test case %d: %I64d\n",cases,ans);
}
return 0;
}