洛谷P3660 [USACO17FEB]Why Did the Cow Cross the Road III G【树状数组】

题目描述

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 NN cows, conveniently identified with the integer IDs 1 \ldots N1…N , so there are precisely 2N2N 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 2N2N 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,b) a “crossing” pair if cow aa ‘s path from entry to exit must cross cow bb ‘s path from entry to exit. Please help Farmer John count the total number of crossing pairs.

输入格式:

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

输出格式:

Please print the total number of crossing pairs.


题目分析

给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足 a i < a j < b i < b j 的对数
意思就是要求交叉对的数量

我们先保存每一对数前后出现的位置x,y
然后将这些坐标按x升序排序

每次查询当前x,y区间中中出现过多少点累加进答案
在令树状数组中y位置加1
因为x是递增的
所以可以保证不会在插入查询过程中出现大的包含小的这样的情况


#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return x*f;
}

void print(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)print(x/10);
    putchar(x%10+'0');
}

int n;
int cnt;
int d[1000010];
struct node{int x,y;}E[1000010];
int sum[1000010];
int ans;
bool cmp(node a,node b){return a.x<b.x;}

int get(int x)
{
    int tot=0;
    for(int i=x;i>0;i-=(i)&(-i)) tot+=sum[i];
    return tot;
}

void update(int x,int v)
{
    for(int i=x;i<=2*n;i+=(i)&(-i))
    sum[i]+=v;
}

int main()
{
    n=read();
    for(int i=1;i<=2*n;i++)
    {
        int x=read();
        if(!d[x]) d[x]=i;
        else { E[++cnt].x=d[x];E[cnt].y=i;d[x]=0; }
    }
    sort(E+1,E+1+cnt,cmp);
    for(int i=1;i<=cnt;i++)
    {
        ans+=get(E[i].y)-get(E[i].x-1);
        update(E[i].y,1);
    }

    print(ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/niiick/article/details/80663968