您的位置:首页 > 其它

poj 3067 Japan 树状数组求逆序对

2016-07-06 19:53 447 查看
传送门

题目大意:

给出t个case,每个case给出k条边,这些边的左右两个端点分别属于n和m两个集合,求出有多少条相交的边(如果两条边有公共端点不算相交)

分析:

显然如果两条边相交一定满足(xi-xj)*(yi-yj)<0,所以我们可以把k条边按照x单调递增的顺序排排序,然后求y的逆序对即可(注意:如果两条边x相同,y按照递增的顺序排,因为这样处理时不会把这两条边算为相交的边Notice!!!)

代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
const int maxn=1000+5;
int cas,n,m,k,t;
LL tr[maxn],ans,ONE=1;
struct road{
int x,y;
}s[maxn*maxn];
bool cmp(road a,road b){
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
void add(int x,LL y){
for(;x<=m;x+=(x&(-x)))
tr[x]+=y;
}
LL query(int x){
LL sum=0;
for(;x;x-=(x&(-x)))
sum+=tr[x];
return sum;
}
signed main(void){
scanf("%d",&cas),t=0;
while(cas--){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
scanf("%d%d",&s[i].x,&s[i].y);
sort(s+1,s+k+1,cmp);
ans=0,memset(tr,0,sizeof(tr));
for(int i=1;i<=k;i++)
add(s[i].y,ONE),ans+=query(m)-query(s[i].y);
t++;
printf("Test case %d: %lld\n",t,ans);
}
return 0;
}


by >o< neighthorn
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: