逆序對+離散化
阿新 • • 發佈:2018-11-11
學習了樹狀陣列就有了樹狀陣列的應用,求逆序對。
首先是如何求用樹狀陣列求逆序對,a陣列表示當前數字出現的次數,樹狀陣列維護當前數字每個數字之前數字有多少比它小的次數。。。描述的可能有誤感性理解一下就好。
add(a[i],1);
void add(int x,int y)
{
for(;x<=n;x+=lowbit(x))c[x]+=y;
}
最後就是查詢當前數字之後有多少比它要小的數字的次數即可~
ans[i]=sum(a[i]-1); int sum(int x) { int tot=0; for(;x;x-=lowbit(x))tot+=c[x];return tot; }
提交上去RE,為什麼呢?因為這裡的數字太大了,把一個數字當作陣列的下標,這是一件很危險的事情所以需要離散,
void discrete() { sort(b+1,b+1+n); int m=unique(b+1,b+1+n)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b; }
這裡b[i]=a[i],程式碼具體什麼意思我也不是很懂具體就是這樣子操作就可以把b數組裡的數字一一對映到n上於是每個數字都不超過n。
還有要開long long 因為這個地方考慮最壞的情況最多的逆序對第n個數有n-1個逆序對,於是n個數字加起來是n^2的數量,炸int。
#include<iomanip> #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<ctime> #include<cstring> #include<string> #include<vector> #include<stack> #include<queue> #include<map> using namespaceView Codestd; inline long long read() { long long x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const long long maxn=500008; long long c[maxn],a[maxn],maxx=-1,ans[maxn],b[maxn]; long long n,m,tot=0; long long lowbit(long long x) { return x&(-x); } void add(long long x,long long y) { for(;x<=n;x+=lowbit(x))c[x]+=y; } void discrete() { sort(b+1,b+1+n); long long m=unique(b+1,b+1+n)-b-1; for(long long i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b; } long long sum(long long x) { long long tot=0; for(;x;x-=lowbit(x))tot+=c[x]; return tot; } int main() { // freopen("1.in","r",stdin); n=read(); for(long long i=1;i<=n;i++)a[i]=read(),b[i]=a[i]; discrete(); for(long long i=n;i>=1;i--) { add(a[i],1); ans[i]=sum(a[i]-1); } for(long long i=1;i<=n;i++)tot+=ans[i]; printf("%lld\n",tot); return 0; }
猝然臨之而不驚,無故加之而不怒~