标签:
一共6种情况,a < b且Aa < Ab, c < d 且Ac > Ad,这两种情况数量相乘,再减去a = c, a = d, b = c, b = d这四种情况,使用树状数组维护,le[i]表示i左边比他小的数数量,le1[i]表示i左边比他大的数数量,ri[i]表示i右边比他小的数数量,ri1[i]表示i右边比他大的数数量。
跑两次树状数组,求出这四个数组值。
注意处理数值相等的情况。
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<utility> using namespace std; typedef long long LL; const int N = 60008, INF = 0x3F3F3F3F; #define MS(a, num) memset(a, num, sizeof(a)) #define PB(A) push_back(A) #define FOR(i, n) for(int i = 0; i < n; i++) int C[N]; int n; int le[N], ri[N], le1[N], ri1[N]; int val[N]; int b[N], tp[N]; inline int lowbit(int x){ return x&-x; } inline void add(int x, int val){ for(int i=x;i<=n;i+=lowbit(i)){ C[i] += val; } } inline int sum(int x){ int ret = 0; for(int i=x;i>0;i-=lowbit(i)){ ret+=C[i]; } return ret; } int main(){ while(~scanf("%d", &n)){ for(int i = 1; i <= n; i++){ scanf("%d", &val[i]); tp[i] = val[i]; } sort(val + 1, val + n + 1); for(int i = 1; i <= n; i++){ b[i] = lower_bound(val + 1, val + n + 1, tp[i]) - val; } MS(C , 0); for(int i = 1; i <= n; i++){ le[i] = sum(b[i] - 1); le1[i] = sum(n) - sum(b[i]); add(b[i], 1); } MS(C, 0); for(int i = n; i >= 1; i--){ ri[i] = sum(b[i] - 1); ri1[i] = sum(n) - sum(b[i]); add(b[i], 1); } LL ans= 0; LL sum = 0; for(int i = n; i >= 1; i--){ sum += ri1[i]; } ans = sum; sum = 0; for(int i = n; i >= 1; i--){ sum += ri[i]; } ans *= sum; sum = 0; for(int i = 1; i <= n; i++){ sum += (LL)ri[i] * (LL)ri1[i]; sum += (LL)ri1[i] * (LL)le1[i]; sum += (LL)le[i] * (LL)le1[i]; sum += (LL)le[i] * (LL)ri[i]; } ans -= sum; printf("%I64d\n", ans); } return 0; }
HDU5792 World is Exploding(树状数组)
标签:
原文地址:http://www.cnblogs.com/IMGavin/p/5732207.html