HDU 5792 World is Exploding
预处理出每个数字前面比它小的有几个,比他大的有几个,后面比他小的有几个,比他大的有几个。
先算出最多可能产生多少对,然后减去多加的就是答案。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } const int maxn=50000+10; int n,a[maxn],b[maxn],c[maxn]; int Lmax[maxn],Lmin[maxn],Rmax[maxn],Rmin[maxn]; int lowbit(int x){return x&(-x);} int sum(int p){ int res=0; while(p) res=res+c[p],p=p-lowbit(p); return res;} void update(int p) { while(p<=n) c[p]=c[p]+1,p=p+lowbit(p); } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i-1]=a[i]; sort(b, b + n); int sz = unique(b, b + n) - b; for(int i=1;i<=n;i++) a[i]=lower_bound(b, b + sz, a[i])-b+1; memset(c,0,sizeof c); for(int i=1;i<=n;i++) { Lmin[i]=sum(a[i]-1); Lmax[i]=sum(n)-sum(a[i]); update(a[i]); } LL S=0; for(int i=1;i<=n;i++) S=S+Lmax[i]; LL ans=0; for(int i=1;i<=n;i++) ans=ans+(LL)(S-Lmax[i])*(LL)Lmin[i]; memset(c,0,sizeof c); for(int i=n;i>=1;i--){ Rmin[i]=sum(a[i]-1); Rmax[i]=sum(n)-sum(a[i]); update(a[i]); } for(int i=1;i<=n;i++) ans=ans-(LL)Rmax[i]*(LL)Rmin[i]-(LL)Rmin[i]*(LL)Lmin[i]-(LL)Rmax[i]*(LL)Lmax[i]; printf("%lld\n",ans); } return 0; }