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

本文介绍了一种求解逆序数的算法,并通过树状数组实现。该问题背景为两队农民攻城,需要计算绳子交叉的数量。文章详细解释了如何通过排序和树状数组求解逆序数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值