hdu 2492 離散化,樹狀陣列,逆序數
阿新 • • 發佈:2019-02-10
題目大意:給出n 個數的序列,列舉一個數,然後查詢該數 左邊大於它的數的個數 a 和小於他的數的個數 b ,查詢右邊大於他的數的個數 c 和小於他的數的個數 d 。
最後,res = a * d + b * c ; 其實就是一個查詢逆序數的過程。
可以用樹狀陣列,和線段樹解決。
這裡要注意一點,如果給出的資料比較大的情況,陣列無法開到這麼大,可以用離散化的思想,把陣列轉化成一個較小的陣列。
樹狀陣列:
#include<iostream> #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> using namespace std; # define N 400000 int inf = 100000000; int maxx[N],b[N],c[N]; int lmin[N],lmax[N],rmin[N],rmax[N]; int n; struct A { int v,index; }a[400000]; int cmp(A p1, A p2) { return p1.v < p2.v; } int lowbit(int x) { return x & (-x); } void update(int x, int y) { while(x <= n) { c[x] += y; x += lowbit(x); } } int getsum(int x) { int ans = 0; while(x > 0) { ans += c[x]; x -= lowbit(x); } return ans; } int main() { int T,i; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(c,0,sizeof(c)); for(i =1 ; i <= n; i++)//離散化 { scanf("%d",&a[i].v); a[i].index = i; } sort(a+1,a+n+1,cmp); for(i = 1; i <= n; i++) b[a[i].index] = i;//離散化 for(i = 1; i <= n; i++) { lmin[i] = getsum(b[i]); lmax[i] = i - lmin[i] - 1; update(b[i],1); } memset(c,0,sizeof(c)); for(i = n; i > 0; i--) { rmin[i] = getsum(b[i]); rmax[i] = n-i - rmin[i]; update(b[i],1); } long long res = 0;//第一次 WA 就是因為這個地方,定義的時候用了int for(i = 1; i <= n; i++) res += lmin[i] * rmax[i] + lmax[i] * rmin[i]; printf("%I64d\n",res); } return 0; }