hdu 5792 World is Exploding(离散化 + 树状数组 + 容斥)
World is Exploding
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 540 Accepted Submission(s): 249
Problem Description
Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.
Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An.
1≤n≤50000
0≤Ai≤1e9
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An.
1≤n≤50000
0≤Ai≤1e9
Output
For each test case,output a line contains an integer.
Sample Input
4
2 4 1 3
4
1 2 3 4
Sample Output
1
0
设下标为a、b、c、d的值为A、B、C、D,要求求出A<B且a<b与C<D且c<d的(a, b, c, d)组合有多少种。设RD为右边比当前数大的数的数量,RX是右边比当前数小的数的数量,同理设LX和LD。计数时会重复的种类是AC重合,AD重合,BC重合,BD重合,分别减去RD * RX,RD * LD,LX * RX,LX * LD。RD、RX、LX、LD通过将数组离散化以后用树状数组求,因为可能会有重复元素,所以求RD和LD的方法和白书上的例题略有不同
#include <bits/stdc++.h> using namespace std; #define ll long long #define ALL(v) (v).begin(), (v).end() const ll maxn = 50010; ll A[maxn], C[maxn], n; ll LX[maxn], RX[maxn], RD[maxn], LD[maxn]; inline ll lowbit(ll x) { return x & (-x); } ll sum(ll x) { ll ret = 0; while(x > 0) { ret += C[x]; x -= lowbit(x); } return ret; } void add(ll x, ll d) { while(x <= maxn) { C[x] += d; x += lowbit(x); } } int main() { ll n; while(~scanf("%I64d", &n)) { vector<ll> v; for(ll i = 1; i <= n; i++) { scanf("%I64d", &A[i]); v.push_back(A[i]); } sort(ALL(v)); v.erase(unique(ALL(v)), v.end()); for(ll i = 1; i <= n; i++) { A[i] = lower_bound(ALL(v), A[i]) - v.begin(); A[i] += 1; } ll L = 0, R = 0; memset(C, 0, sizeof(C)); for(ll i = 1; i <= n; i++) { add(A[i], 1); LX[i] = sum(A[i] - 1); LD[i] = (i - sum(A[i])); L += LX[i]; } memset(C, 0, sizeof(C)); for(ll i = n; i >= 1; i--) { add(A[i], 1); RX[i] = sum(A[i] - 1); RD[i] = (n - i + 1 - sum(A[i])); R += RX[i]; } ll ans = L * R; for(ll i = 1; i <= n; i++) { ans -= RD[i] * RX[i]; ans -= RD[i] * LD[i]; ans -= LX[i] * RX[i]; ans -= LX[i] * LD[i]; } printf("%I64d\n", ans); } }