Why Did the Cow Cross the Road III - UPCOJ 3439 - 树状数组

本文介绍了一道关于计算牛群在圆形农场中路径交叉次数的问题。通过分析给出的牛穿越路径序列,利用数据结构实现了高效求解算法。

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

链接:

  http://exam.upc.edu.cn/problem.php?id=3439


题目:

题目描述

The layout of Farmer John’s farm is quite peculiar, with a large circular road running around the perimeter of the main field on which his cows graze during the day. Every morning, the cows cross this road on their way towards the field, and every evening they all cross again as they leave the field and return to the barn.
As we know, cows are creatures of habit, and they each cross the road the same way every day. Each cow crosses into the field at a different point from where she crosses out of the field, and all of these crossing points are distinct from each-other. Farmer John owns N cows, conveniently identified with the integer IDs 1…N, so there are precisely 2N crossing points around the road. Farmer John records these crossing points concisely by scanning around the circle clockwise, writing down the ID of the cow for each crossing point, ultimately forming a sequence with 2N numbers in which each number appears exactly twice. He does not record which crossing points are entry points and which are exit points.

Looking at his map of crossing points, Farmer John is curious how many times various pairs of cows might cross paths during the day. He calls a pair of cows (a,b) a “crossing” pair if cow a’s path from entry to exit must cross cow b’s path from entry to exit. Please help Farmer John count the total number of crossing pairs.

输入

The first line of input contains N (1≤N≤50,000), and the next 2N lines describe the cow IDs for the sequence of entry and exit points around the field.

输出

Please print the total number of crossing pairs.

样例输入

4
3
2
4
4
1
3
2
1

样例输出

3


题意:

  一个圆环上顺时针有一些点排布,问你把每两个相同的点连起来,有几条线是相交的。


思路:

  观察数组,发现如果在两个相同的点之间,存在只出现了一次的数字,那么这两个数字所对应的线一定是相交的,所以问题就转化成了查询每个相同数字之间出现了奇数次的数字的个数。


实现:

#include <iostream>
#include <algorithm>
#include <set>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <climits>
#include <cctype>
using namespace std;
const int maxn = int(1e5)+7;
struct N{
    int l,r;
    bool operator < (const N& tmp) const {
        if(l == tmp.l) return r < tmp.r;
        return l < tmp.l;
    }
}a[maxn];
int n,c[maxn];

int lowbit (int x) {return x & -x;}
void update (int x) {
    for (register int i = x ; i <= n<<1 ; i += lowbit(i)) c[i] += 1;
}
int sum(int x) {
    int ans = 0;
    for (register int i=x ; i != 0 ; i -= lowbit(i)) ans += c[i];
    return ans;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    ios_base::sync_with_stdio(false);cin.tie(nullptr);
    cin >> n;
    for(int i = 1, tmp ; i <= n<<1 ; i++)
        cin >> tmp, a[tmp].l == 0 ? a[tmp].l = i : a[tmp].r = i;
    sort(a+1,a+1+n);
    int result {};
    for(int i = 1 ; i <= n ; i++) update(a[i].r + 1), result += sum(a[i].r) - sum(a[i].l);
    cout << result << '\n';
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值