F. 正序的人生
Description
给定一个n个元素的数组,这个数组由1…n的一个排列,输出其中满足ai<aj<ak(i<j<k)的个数
Input
第一行正整数n(3<=n<=100000),接下来n个数,为1…n一个排列,保证输入的每个数不重复且均属于[1,n]
Output
输出满足条件的个数,结果对1000000007取余。
Sample Input
5
1 3 2 4 5
Sample Output
7
这个题是上次那个逆序的人生改的题,之前那个是逆序对,这次要判断连续的三个,故可以从中间入手,将中间数前面的比它小数的个数乘以后面比它大数的个数累加即为所求。
关键部分还是query函数,返回比a[i]小或者等于的数的个数,i-query(a[i])就是前i个数中大于a[i]的数的个数,(n-a[i])-(i-query(a[i]))就是后面比它大数的个数,而比它小的就是query(a[i])-1。
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
int n,a[maxn],s[maxn];
int lowbit(int x)
{
return x&(-x);
}
void modify(int pos,int val)
{
while(pos<=n)
{
s[pos]+=val;
pos+=lowbit(pos);
}
}
int query(int end)
{
int sum=0;
while(end>0)
{
{
sum+=s[end];
end-=lowbit(end);
}
}
return sum;
}
int main()
{
int i,j,k,ans;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
s[i]=0;
ans=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
modify(a[i],1);
ans=(ans+(__int64)(query(a[i]-1)*(__int64)((n-a[i])-(i-query(a[i])))))%1000000007;
}
printf("%d\n",ans);
}
return 0;
}