朗格拉日计算
Time Limit: 10 Sec Memory Limit: 128 MBDescription
Input
Output
仅一行一个整数表示答案。
Sample Input
5
3 2 5 4 1
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }