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 }

 

posted @ 2015-05-20 09:52  miao_a_miao  阅读(137)  评论(0编辑  收藏  举报