POJ 1794 Castle Walls(逆序数)#by zh

来源:互联网 发布:阿里云个人网站 编辑:程序博客网 时间:2024/04/29 23:12
这道题的题意还是比较简单的,有两队农民要把钩子扔到对面的城墙上然后爬上去攻城,每个人都有一个编号,城墙也有对应的编号,现在保证一个队伍中的人扔上去的绳子不可能交叉,问你有几对人的绳子相互交叉。做题前看这题是一个求逆序数的题还没一点思路,后来在网上看到了别人的思路才明白了一些。首先要把每个人的位置和对于城墙的编号读入,然后按照城墙编号升序排序,如果城墙编号相同,则按农民编号降序排列,这样通过构造农民编号的逆序的方法,求逆序数的个数来得到问题的答案。逆序数的求法有不少,我用树状数组求的,感觉这种方法还是比归并排序简单一点,顺便复习一下这个好久没用的数据结构……
#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);    }}