题目背景
给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数
题目描述
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.
输入输出样例
输入样例#1:
4 3 2 4 4 1 3 2 1
输出样例#1:
3
解:这题用树状数组就可以做出来了,难度一般。先预处理好所有的数字的两个位置。
我们可以对每段区间左边和右边分别进行求和,并取最小值。
进行累加就可以得到答案了。 嗯。。。类似求逆序对的方法
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; #define man 50010 #define lo(x) (x&(-x)) #define read(x) scanf("%d",&x) /*TEST*/ int n; struct node { int x,y;}e[man<<2]; /*B_TREE*/ int c[man<<2]; inline void update(int x,int val) { while(x<=2*n) { c[x]+=val; x+=lo(x); } return ; } inline int query(int x) { int ans=0; while(x>0) { ans+=c[x]; x-=lo(x); } return ans; } inline int calc(int x,int y) { int l=query(x); int r=query(y); r=r-l; return min(l,r);//从1位置到左端点,从左端点位置+1到右端点 } /*SORT*/ inline int cmp(node a,node b) { return a.x<b.x;} int main() { read(n); for(int i=1;i<=2*n;i++) { int tmp;read(tmp); if(e[tmp].x>0) e[tmp].y=i; else e[tmp].x=i; } sort(e+1,e+1+n,cmp); int ans=0; for(int i=1;i<=n;i++) { ans+=calc(e[i].x,e[i].y); update(e[i].x,1); update(e[i].y,1); } printf("%d\n",ans); return 0; }