题意:
左侧有一列点..从上到下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; }