题目链接:http://poj.org/problem?id=3067
题目大意:给出t个样例
每个样例给出n个左边的点 m个右边的点 k条左边点连右边点的线
问最多有几个交点,每个交点最多有两条线经过
思路:
一:总体的思路
先来分析下什么样的情况两条线会有交点:即相交的情况必然是在在Li<Lj的情况下,Ri>Rj
所以我们先按照左边的由小到大的顺序排序,在对每条线查找右边点比他的个数
二:排序
struct node
{
int s,e;
bool operator <(const node &tmp)const
{
if(s==tmp.s)return e<tmp.e;
return s<tmp.s;
}
}nodes[MAXN];
即左边先按由小到大的顺序,当左边相等时,右边按由小到大的顺序.
因为,当左边点相等时,这两条线必定不可能相交,为了排除这种情况,当左边点相同时,让右边点小的先出现,这样就不会将左边点相同右边点比他大的直线记录进去!!
还有需要注意的是:
ret+=i-getSum(id); 因为是大于他的个数,所以转化为当前条数减去小于等于他的条数.
还有本题数据较大,需要将结果设为long long
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN =1000010;
struct node
{
int s,e;
bool operator <(const node &tmp)const
{
if(s==tmp.s)return e<tmp.e;
return s<tmp.s;
}
}nodes[MAXN];
int n,m,k;
int treenum[MAXN];
int lowbit(int x){
return x&(-x);
}
long long getSum(int x){//一维
long long sum = 0;
while(x){//将以x为根节点的数 相当于求其叶节点的和 但其非叶节点等于其两个子节点的和
sum += treenum[x];
x -= lowbit(x);
}
return sum;
}
void add(int x , int val){//一维
while(x < MAXN){//相当于一个树 他将其自己以及他的父节点一路向上都加val
treenum[x] += val;
x += lowbit(x);
}
}
long long solve()
{
memset(treenum,0,sizeof treenum);
sort(nodes,nodes+k);
long long ret=0;
for(int i=0;i<k;i++)
{
int id=nodes[i].e;
ret+=i-getSum(id);
add(id,1);
}
return ret;
}
int main(){
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<k;i++)
{
scanf("%d%d",&nodes[i].s,&nodes[i].e);
}
printf("Test case %d: %lld\n" ,cas, solve());
}
return 0;
}