题意:
东西海岸线分别有n,m坐城市,要修k条公路,求这k条公路的交叉点
思路:
将公路的 x(s) 按照从小到大的顺序排序,若 x 点相同,则将 y (e) 小的放在前边。两公路如果相交则 ( Xi<Xj & Yi>Yj )。
如果在求第k条公路的交点时,前 k-1 条公路的 x 都比他小,我们只需求出这 k-1 条公路有几条 y 比他大就有几个交点。
也可以让 x,y都按照从大到小的顺序排序,但是不能一个从小到大,一个从大到小。(假设 x 从小到大排序)如果当 x 相等的时候时候,如果把 y 大的放前面,计算他后面那个 x 值相等的点的时候,前面 y 比他大错误的加上了1,所以当 x 相等的时候必须按 y 从小到大排序!
注意
求和要用 long long
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll c[1010*1010];
int n,m,k;
struct node
{
int s,e;
}p[1010*1010];
bool cmp(node a,node b)
{
if(a.s==b.s)
return a.e<b.e;
else
return a.s<b.s;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int v)
{
while(x<=m)
{
c[x] += v;
x += lowbit(x);
}
}
ll sum(int x)
{
ll ans=0;
while(x>0)
{
ans += c[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
memset(c,0,sizeof(c));
scanf("%d%d%d",&n,&m,&k);
for(int j=1;j<=k;j++)
scanf("%d%d",&p[j].s,&p[j].e);
sort(p+1,p+1+k,cmp);
ll cnt=0;
for(int j=1;j<=k;j++)
{
cnt += (sum(m)-sum(p[j].e));
add(p[j].e,1);
}
printf("Test case %d: %lld\n",i,cnt);
}
return 0;
}