小奇遐想
题目描述
小奇望着青天中的悠悠白云,开始了无限的遐想,在它的视野中,恰好有n朵高度不同的白云排成一排,他想从左到右选出四朵白云a,b,c,d,使得h_a < h_b < h_d < h_c,即看起来像是彩虹的形状!它想知道有多少种方案数。
输入格式
第一行包括1个整数n。
第二行包括n个整数,第i 个正数表示h_i,保证这n个整数是n的一个全排列。
输出格式
输出一个整数表示答案。(mod 16777216)
样例
样例输入1
5
1 5 3 2 4
样例输出1
0
样例输入2
4
1 2 4 3
样例输出2
1
数据范围与提示
对于10%的数据n<=600;
对于40%的数据n<=5000;
对于100%的数据n<=200000。
1 #include<cstdio> 2 const int maxn=200000+10,mod=16777216; 3 typedef long long ll; 4 int h[maxn]; 5 ll c[maxn],l[maxn],r[maxn],z[maxn],lsum[maxn]; 6 int n; 7 void update(int x,int w){ 8 while(x<=n){ 9 c[x]+=w; 10 x+=x&(-x); 11 } 12 } 13 ll query(int x){ 14 ll ans=0; 15 while(x){ 16 ans+=c[x]; 17 x-=x&(-x); 18 } 19 return ans; 20 } 21 void update1(int x,int w){ 22 while(x<=n){ 23 z[x]+=w; 24 x+=x&(-x); 25 } 26 } 27 ll query1(int x){ 28 ll ans=0; 29 while(x){ 30 ans+=z[x]; 31 x-=x&(-x); 32 } 33 return ans; 34 } 35 int main(){ 36 scanf("%d",&n); 37 for(int i=1;i<=n;i++) scanf("%d",&h[i]); 38 ll ans=0; 39 for(int i=1;i<=n;i++){ 40 update(h[i],1); 41 l[i]=query(h[i]-1); 42 r[i]=n-h[i]-i+l[i]+1; 43 update1(h[i],l[i]); 44 lsum[i]=query1(h[i]-1); 45 } 46 for(int i=2;i<=n-2;i++) ans=(ans+l[i]*r[i]*(r[i]-1)/2)%mod; 47 for(int i=3;i<=n-1;i++){ 48 ans=(ans-lsum[i]*r[i]+mod)%mod; 49 if(ans<0) ans+=mod; 50 } 51 printf("%lld ",ans); 52 return 0; 53 }