标签:
【算法】求逆序对(树状数组)(也可以用归并排序等)
【题解】
学自:http://blog.csdn.net/greatwjj/article/details/16808243
https://vijos.org/p/1842/solution(从下往上第三个回答)
因此要使结果最小,只要最大化aibi(i=1...n),即使小的数对应小的数,大的数对应大的数。
1.对于数列a,b先离散化,将他们值替换为他们在所在数列的排名。
2.令数列c记录a中每个数应该在b中的位置(a的目标位置)。
3.对数列c求逆序对的数量。
#include<cstdio> #include<algorithm> #include<cstring> #define lowbit(x) x&(-x) using namespace std; const int maxn=100010,mod=99999997; struct cyc{int v,ord;}p[maxn],pa[maxn]; bool cmp(cyc a,cyc b){return a.v<b.v;} int a[maxn],n,s[maxn];long long ans; void give(int x) { for(int i=x;i<=n;i+=lowbit(i))s[i]++; } int ask(int x) { int anss=0; for(int i=x;i>0;i-=lowbit(i))anss+=s[i]; return anss; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&pa[i].v),pa[i].ord=i; sort(pa+1,pa+n+1,cmp); // for(int i=1;i<=n;i++)a[pa[i].ord]=i;//printf("[a]");for(int i=1;i<=n;i++)printf("%d ",a[i]);printf("\n"); for(int i=1;i<=n;i++)scanf("%d",&p[i].v),p[i].ord=i; sort(p+1,p+n+1,cmp); for(int i=1;i<=n;i++)a[pa[i].ord]=p[i].ord; // printf("[b]");for(int i=1;i<=n;i++)printf("%d ",b[i]);printf("\n"); // printf("[c]");for(int i=1;i<=n;i++)printf("%d ",a[i]);printf("\n"); for(int i=1;i<=n;i++) { give(a[i]); (ans+=(i-ask(a[i])))%=mod; } printf("%lld",ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/onioncyc/p/5768905.html