hdoj 2838
题目大意:给出数,求排成正序的最少时间,每两个数交换的时间是 两个数的值的和。
解决:树状数组,只需求出 在这个数加入之前比这个数大的个数,然后更新,再求出这个数加入之前比这个数大的数的总和
总共的代价是:cnt*加入的数+比这个数大的数的和
#include <iostream> #include <functional> #include <algorithm> using namespace std; #define LL __int64 const int N=100000; LL sum[N+5]; //第i个数前比数num[i]大的数的和 LL cnt[N+5]; //第i个数前比数num[i]大的数的个数 inline int lowbit(int x) { return x&(-x); } void update(LL t[],int p,int delta) { for(int i=p;i>0;i-=lowbit(i)) t[i]+=delta; } LL getsum(LL t[],int p) { LL tot=0; for(int i=p;i<=N;i+=lowbit(i)) tot+=t[i]; return tot; } int main() { int n, t; scanf("%d",&n); LL ans=0; for(int i=1;i<=n;i++) { scanf("%d",&t); //注意这个tmp必须是LL长整型的 LL tmp=getsum(cnt,t+1); update(cnt,t,1); //这个s必须是长整型的,就是这个地方错了好几次的。 LL s=getsum(sum,t+1); update(sum,t,t); ans += tmp*t+s; } printf("%I64d\n",ans); system("pause"); return 0; }