这道题的题意还是比较简单的,有两队农民要把钩子扔到对面的城墙上然后爬上去攻城,每个人都有一个编号,城墙也有对应的编号,现在保证一个队伍中的人扔上去的绳子不可能交叉,问你有几对人的绳子相互交叉。做题前看这题是一个求逆序数的题还没一点思路,后来在网上看到了别人的思路才明白了一些。首先要把每个人的位置和对于城墙的编号读入,然后按照城墙编号升序排序,如果城墙编号相同,则按农民编号降序排列,这样通过构造农民编号的逆序的方法,求逆序数的个数来得到问题的答案。逆序数的求法有不少,我用树状数组求的,感觉这种方法还是比归并排序简单一点,顺便复习一下这个好久没用的数据结构……
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#define lowbit(x) (x&(-x))
using namespace std;
int n,m;
struct Node
{
int x,y;
}pos[60005];
int a[60005];
void modify(int pos,int c)
{
while(pos<=n+m)
{
a[pos]+=c;
pos+=lowbit(pos);
}
}
long long query(int pos)
{
long long ans=0;
while(pos>0)
{
ans+=a[pos];
pos-=lowbit(pos);
}
return ans;
}
bool cmp(Node a,Node b)
{
if(a.y==b.y)
return a.x>b.x;
return a.y<b.y;
}
int main()
{
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
memset(a,0,sizeof(a));
if(cas!=1)
printf("\n");
printf("Scenario #%d:\n",cas);
int x,y;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d%d",&pos[i].x,&pos[i].y);
for(int i=0;i<m;i++)
scanf("%d%d",&pos[i+n].x,&pos[i+n].y);
sort(pos,pos+n+m,cmp);
long long ans=0;
for(int i=0;i<n+m;i++)
{
modify(pos[i].x,1);
ans+=pos[i].x-query(pos[i].x);
}
printf("%lld\n",ans);
}
}