Paper Plane Fly Away(2019hbcpc)
题目链接:https://ac.nowcoder.com/acm/contest/903/E
解题思路:把喜欢女孩的序列映射成女孩所坐的位置序列,就可知只需要求第i个数前面有几个较大数,后边有几个较小数就是答案,既求逆序对问题。按顺序将序列依次插入树状数组中,权值为1,利用树状数组性质,可以快速求出前i项和,正反插入两次,即可求出全部需要的逆序对数量。
AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<cmath> using namespace std; #define ll long long #define ull unsigned long long #define ldb long double #define lowbit(x) (x&-x) #define db double #define fi first #define se second #define INF 0x3f3f3f3f #define endl "\n" #define rush() int T;scanf("%d",&T);while(T--) #define mem(a,b) memset((a),(b),sizeof(a)) const db pi = acos((db)-1); const ll MAXN = 1e5; const ll mod = 1e9+7; int a[MAXN+2],b[MAXN+2]; int s[MAXN+2]; int f[MAXN+2]; void add(int i, int x) { while(i<MAXN)f[i]+=x,i+=lowbit(i); } int sum(int i) { int res=0; while(i)res+=f[i],i-=lowbit(i); return res; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdin); mem(s,0); int n; scanf("%d",&n); for(int i=1;i<=n;i++) { int c; scanf("%d%d",&c,&b[i]); c-=n; a[c]=i; b[i]-=n; } for(int i=1;i<=n;i++)b[i]=a[b[i]]; mem(f,0); for(int i=1;i<=n;i++) { add(b[i],1); s[i]+=sum(n+1)-sum(b[i]); } mem(f,0); for(int i=n;i>0;i--) { s[i]+=sum(b[i]); add(b[i],1); } for(int i=1;i<=n;i++)printf("%d\n",s[i]); return 0; }