World is Exploding
题意:
给出一个长为n的序列A,问有多少四元组(a, b, c, d)满足$a \ne b \ne c \ne d, 1 \leq a < b \leq n, 1 \leq c < d \leq n, A_a < A_b, A_c > A_d$.
解法:
容斥,考虑用正序对乘以逆序对后,得到的方案中四种不合法情况:
1.$c < d = a < b$
2.$a < b = c < d$
3.$a = c < d$ 且 $a = c < d$
4.$a < b = d$ 且 $c < b = d$
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 50010 #define LL long long #define lb(x) (x&(-x)) using namespace std; int n, tot; int a0[N], a[N], pre[N], suc[N]; int ask(int sum[], int x) { int ans = 0; for(int i = x; i > 0; i -= lb(i)) ans += sum[i]; return ans; } void add(int sum[], int x, int v) { for(int i = x; i <= tot && i>0;i += lb(i)) sum[i] += v; } LL qsum(int sum[], int l, int r) { if(l > r) return 0; return ask(sum, r) - ask(sum, l - 1); } int main() { while(~scanf("%d", &n)) { for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); a0[i] = a[i]; suc[i] = 0; pre[i] = 0; } sort(a0 + 1, a0 + n + 1); tot = 1; for(int i = 2; i <= n; i++) if(a0[i] != a0[i-1]) a0[++tot] = a0[i]; for(int i = 1; i <= n; i++) { a[i] = lower_bound(a0 + 1, a0 + tot + 1, a[i]) - a0; add(suc, a[i], 1); } LL ans = 0, cnt1 = 0, cnt2 = 0; for(int i = 1; i <= n; i++) { add(pre, a[i], 1); add(suc, a[i], -1); LL pre_higher = qsum(pre, a[i] + 1, tot); LL pre_lower = qsum(pre, 1, a[i] - 1); LL suc_higher = qsum(suc, a[i] + 1, tot); LL suc_lower = qsum(suc, 1, a[i] - 1); cnt1 += suc_higher; cnt2 += suc_lower; ans -= pre_higher * suc_higher; ans -= pre_lower * suc_lower; ans -= suc_lower * suc_higher; ans -= pre_lower * pre_higher; } ans += cnt1 * cnt2; cout << ans << endl; } return 0; }