【Foreign】朗格拉日计数 [暴力]

朗格拉日计算

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

  

Input

  

Output

  仅一行一个整数表示答案。

Sample Input

  5
  3 2 5 4 1

Sample Output

  4

HINT

  

Main idea

  将一个排列围成一个环,每个点有一个值a[i],若顺时针三个点A、B、C 满足 a[A]<a[B]<a[C] 则可以统计答案,询问答案。

Solution

  我们不考虑环,从序列考虑,显然可以统计的就是类似这种:123、231、312这个样子的。

  我们考虑容斥,显然123这种是可以直接计算的,231就是xx1 - 321,312就是3xx - 321。

  显然我们这样这样用树状数组统计一下 f[i] 表示 i 前面<a[i]的个数,然后就可以计算出:前面<a[i]的个数、前面>a[i]的个数、后面<a[i]的个数、后面>a[i]的个数

  然后这样暴力计算即可。

Code

 1 #include<iostream>  
 2 #include<algorithm>  
 3 #include<cstdio>  
 4 #include<cstring>  
 5 #include<cstdlib>  
 6 #include<cmath>  
 7 using namespace std;
 8 typedef long long s64;
 9 const int ONE = 1000001;
10 const int MOD = 1e9+7;
11 
12 int n;
13 int a[ONE],f[ONE];
14 s64 Ans;
15 
16 int get()
17 { 
18         int res=1,Q=1;    char c;
19         while( (c=getchar())<48 || c>57)
20         if(c=='-')Q=-1;
21         if(Q) res=c-48; 
22         while((c=getchar())>=48 && c<=57) 
23         res=res*10+c-48; 
24         return res*Q; 
25 }
26 
27 s64 C(int n)
28 {
29         return (s64)n*(n-1)/2;
30 }
31 
32 
33 namespace Bit
34 {
35         int C[ONE];
36         
37         int lowbit(int x)
38         {
39             return x&-x;
40         }
41     
42         void Add(int R,int x)
43         {
44             for(int i=R;i<=n;i+=lowbit(i))
45                 C[i]+=x;
46         }
47         
48         int Query(int R)
49         {
50             int res=0;
51             for(int i=R;i>=1;i-=lowbit(i))    
52                 res+=C[i];
53             return res;
54         }
55 }
56 
57 int pre_min(int i) {return f[i];}
58 int pre_max(int i) {return i-1-f[i];}
59 int suc_min(int i) {return a[i]-1-pre_min(i);}
60 int suc_max(int i) {return n-a[i]-pre_max(i);}
61 
62 int main()
63 {
64         n=get();
65         for(int i=1;i<=n;i++)    a[i]=get();
66         
67         for(int i=1;i<=n;i++)
68         {
69             Bit::Add(a[i],1);
70             f[i] = Bit::Query(a[i]-1);
71         }
72         
73         for(int i=1;i<=n;i++)
74         {
75             Ans += (s64)pre_min(i) * suc_max(i);
76             Ans += C( pre_max(i) );
77             Ans += C( suc_min(i) );
78             Ans -= (s64)2 * pre_max(i) * suc_min(i); 
79         }
80         
81         printf("%lld",Ans);
82 }
View Code

 

posted @ 2017-03-08 20:15  BearChild  阅读(1125)  评论(0编辑  收藏  举报