楼兰图腾——逆序数
题意:
在给定的序列中,可以构成多少个‘v’ 和 ‘^’
题解:
‘v‘的解法
由于序列中的数是从小到大给出的,所以我们如果知道a[i]的前面有多少个比他大的数a[i]的后面有多少个比他大的数,那么可以构成的V就是这两个数之积,而最终答案ans就是所有位置积的累加
同理’^‘的解法同理
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+5; ll n,m; ll c[maxn],a[maxn]; ll ldown[maxn],rdown[maxn],lup[maxn],rup[maxn]; void update(ll pos,ll x) { for(ll i=pos;i<=n;i+=i&-i)c[i]+=x; } ll query(ll pos) { ll ans=0; for(ll i=pos;i;i-=i&-i)ans+=c[i]; return ans; } int main() { scanf("%lld",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } for(int i=1;i<=n;i++) { update(a[i],1); ldown[i]=query(a[i]-1); } memset(c,0,sizeof c); for(int i=n;i>0;i--) { update(a[i],1); rdown[i]=query(a[i]-1); } memset(c,0,sizeof c); for(int i=1;i<=n;i++) { update(a[i],1); lup[i]=i-query(a[i]); // printf("%d==%d\n",i,lup[i]); } memset(c,0,sizeof c); for(int i=n;i>0;i--) { update(a[i],1); rup[i]=(n-i+1)-query(a[i]); //printf("%d==%d\n",i,rup[i]); } ll ans1=0; for(int i=1;i<=n;i++)ans1+=ldown[i]*rdown[i]; ll ans2=0; for(int i=1;i<=n;i++)ans2+=lup[i]*rup[i]; printf("%lld %lld\n",ans2,ans1); return 0; }