vijos p1768 数学

链接:点我

预处理:b[i][j]表示a[1] ... a[j]中比a[i]小的数的数量。

int get_lower_count(int b[], int l, int r)
{
return b[r] - b[l - 1];
}
枚举左端点i,右端点j,则 get_lower_count(b[j], i + 1, j) - get_lower_count(b[i], i, j)为a[i]...a[j]的“顺序对的值”。因为a...a[j-1]中的值只有3种情况,要么比a[j]大,要么在a[i]与a[j]之间,要么比 a[i]小。比a[i]小的数,必然比a[j]小。所以用比a[j]小的数剪掉比a[i]小的数即可。

 1 #include<cstdio>

 2 #include<iostream>

 3 #include<algorithm>

 4 #include<cstring>

 5 #include<cmath>

 6 #include<queue>

 7 #include<map>

 8 using namespace std;

 9 #define MOD 1000000007

10 const int INF=0x3f3f3f3f;

11 const double eps=1e-5;

12 typedef long long ll;

13 #define cl(a) memset(a,0,sizeof(a))

14 #define ts printf("*****\n");

15 const int MAXN=5005;

16 int n,m,tt,a[MAXN],f[MAXN][MAXN];   //1到j中比a[i]小的数

17 int main()

18 {

19     int i,j,k;

20     /*#ifndef ONLINE_JUDGE

21     freopen("1.in","r",stdin);

22     #endif*/

23     scanf("%d",&n);

24     for(i=1;i<=n;i++)

25     {

26         scanf("%d",a+i);

27     }

28     cl(f);

29     for(i=1;i<=n;i++)

30     {

31         f[i][1]=(a[i]>a[1]);

32         for(j=2;j<=n;j++)

33         {

34             f[i][j]=f[i][j-1]+(a[j]<a[i]);

35         }

36     }

37     long long ans=0,ans1,ans2;

38     for(i=1;i<n;i++)

39     {

40         for(j=i+2;j<=n;j++)

41         {

42             if(a[j]>a[i])

43             {

44                 ans1=f[j][j]-f[j][i];   //i到j内比a[j]小的数(注意这里不包含i和j)

45                 ans2=f[i][j]-f[i][i];   //i到j内比a[i]小的数

46                 ans+=(ans1-ans2);

47                 //printf("%d %d %d %d %d\n",i,j,ans1,ans2,ans);

48             }

49         }

50     }

51     printf("%I64d\n",ans);

52 }

 

你可能感兴趣的:(OS)