数列(sequence.pas/c/cpp)
- 问题描述
一个简单的数列问题:给定一个长度为n的数列,求这样的三个元素ai, aj, ak的个数,满足ai < aj > ak,且i < j < k。
- 输入数据
第一行是一个整数n(n <= 50000)。
第二行n个整数ai(0 <= ai <= 32767)。
- 输出数据
一个数,满足ai < aj > ak (i < j < k)的个数。
- 样例输入
5
1 2 3 4 1
- 样例输出
6
分析:思路类似问题 A,先求出一个数左边有多少比它小,再求出一个数的右边有多少比它小。而问题 A 中已经知道了前面怎么求,那么求右边有多少比它大,可以把这个数组反过来存,问题就转化为求左边有多少比它小。
#include<algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <queue>
#include <stack>
#include <ctime>
#include <cmath>
#include <map>
#include <set>
#define INF 0x3fffffff
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<endl
#define db5(x,y,z,r,w) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#r<<"="<<(r)<<", "<<#w<<"="<<(w)<<endl
using namespace std;
#define lowbit(i) ((i)&(-i))
typedef struct node
{
int val,pos;
}node;
long long getsum(int x,int n,int c[])
{
long long sum=0;
for(int i=x;i>0;i-=lowbit(i))
sum+=c[i];
return sum;
}
void update(int x,int v,int n,int c[])
{
for(int i=x;i<=n;i+=lowbit(i))
c[i]+=v;
return;
}
bool cmp(node a,node b)
{
return a.val<b.val;
}
int main(void)
{
#ifdef test
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
clock_t start=clock();
#endif //test
int n;
while(~scanf("%d",&n))
{
node num[n+5];
int c1[n+5]={0},c2[n+5]={0},a[n+5]={0},b[n+5]={0};
for(int i=0;i<n;++i)
scanf("%d",&num[i].val),num[i].pos=i;
sort(num,num+n,cmp);
for(int i=0;i<n;++i)
{
if(i==0||num[i].val!=num[i-1].val)a[num[i].pos]=i+1;
else a[num[i].pos]=a[num[i-1].pos];
}
for(int i=0;i<n;++i)
b[i]=a[n-1-i];
long long ans=0;
long long sum1[n+5]={0},sum2[n+5]={0};
for(int i=0;i<n;++i)
{
update(a[i],1,n,c1);sum1[i]=getsum(a[i]-1,n,c1);
update(b[i],1,n,c2);sum2[n-1-i]=getsum(b[i]-1,n,c2);
}
for(int i=0;i<n;++i)
ans+=sum1[i]*sum2[i];
printf("%lld\n",ans);
}
#ifdef test
clockid_t end=clock();
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
printf("\n\n\n\n\n");
cout<<"Total time:"<<endtime<<"s"<<endl; //s为单位
cout<<"Total time:"<<endtime*1000<<"ms"<<endl; //ms为单位
#endif //test
return 0;
}
最后记录一下《算法笔记》书练习的 AC 代码:codeup/13.2树状数组 at master · maximusyoung007/codeup · GitHub