题目大意:
有两条平行线,给出n条分别连接两条平行线上整点的线段
保证不会有重边且不会与两条以上边交于一个点的情况
思路:
画图可以得知,当且仅当两条线段在两条平行线上端点的大小关系相反时,才会相交
因此我们可以使用树状数组
按照第二条平行线上的位置升序排序
然后倒着查询之前有(即在它右边)几个比它在第一条平行线上位置小的就可以
但是有一个特殊情况:当他们在第二条平行线上位置相等时不算有交点
因此我们在排序时,若为特殊,则按照第一条的位置升序,就在倒着插入查询时可以避免错误的计算
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstring>
6 #include<cstdlib>
7 #include<queue>
8 #include<vector>
9 #include<set>
10 #include<map>
11 #include<stack>
12 #define inf 2147483611
13 #define ll long long
14 #define MAXN 1001001
15 using namespace std;
16 inline int read()
17 {
18 int x=0,f=1;
19 char ch=getchar();
20 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
21 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
22 return x*f;
23 }
24 struct data
25 {
26 int l,r;
27 bool operator < (const data &a) const
28 {
29 return (r<a.r)||(r==a.r&&l<a.l);
30 }
31 }a[MAXN];
32 int n,m,k,c[MAXN];
33 int lowbit(int x) {return x&(-x);}
34 void add(int x) {for(int i=x;i<=1010;i+=lowbit(i)) c[i]++;}
35 int sum(int x)
36 {
37 int ans=0;
38 for(int i=x;i;i-=lowbit(i)) ans+=c[i];
39 return ans;
40 }
41 int main()
42 {
43 ll ans;
44 int T=read();
45 for(int t=1;t<=T;t++)
46 {
47 memset(c,0,sizeof(c));
48 n=read(),m=read(),k=read();
49 for(int i=1;i<=k;i++) a[i].l=read(),a[i].r=read();
50 sort(a+1,a+k+1);
51 ans=0;
52 add(a[k].l);
53 for(int i=k-1;i>=1;i--)
54 {
55 ans+=sum(a[i].l-1);
56 add(a[i].l);
57 }
58 printf("Test case %d: %lld
",t,ans);
59 }
60 }