『USACO』Why Did the Cow Cross the Road III G (树状数组)

题目链接

题目描述

Description

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 \ldots 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.


中文翻译

给定长度为\(2N\)的序列,\(1\sim N\)各处现过2次,\(i\)第一次出现位置记为\(a_i\),第二次记为\(b_i\),求满足\(a_i<a_j<b_i<b_j\)的对数。



解题思路

偏序类问题,我们首先固定一维顺序,便于计算。

我们按照\(a\)从小到大排序,我们从小到达枚举每一个\(j\)时,前面的已经被枚举过了,我们只需要看前面有多少个数的\(b_i\)大于\(a_j\)且小于\(b_j\),显然,我们可以使用树状数组维护。

还有不懂的可以看代码(●'◡'●)



代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define lowbit(x) x&-x
using namespace std;
const int maxn=100050;
int n;
int a[maxn<<1],num[maxn<<3];
struct nod{
    int l,r;
};
nod b[maxn];
inline bool cmp(nod x,nod y){
    return x.l<y.l;
}
inline void add(int x){
    while(x<=(maxn<<1)){
        num[x]++;
        x+=lowbit(x);
    }
}
inline int query(int x){
    int ans=0;
    while(x>0){
        ans+=num[x];
        x-=lowbit(x);
    }
    return ans;
}
int main(){
    scanf("%d",&n);
    for(register int i=1;i<=(n<<1);i++){
        scanf("%d",&a[i]);
        if(!b[a[i]].l)b[a[i]].l=i;
        else b[a[i]].r=i;
    }
    sort(b+1,b+n+1,cmp);
    int ans=0;
    for(register int i=1;i<=n;i++){
        ans+=query(b[i].r-1)-query(b[i].l);
        add(b[i].r);
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自www.cnblogs.com/Fang-Hao/p/9710734.html