CodeForces 61E Enemy is weak 【树状数组】

题目:点击打开链接

题意:给定一个数列,求出多少组满足条件的数,使得下标i<j<k且ai>aj>ak

分析:很显然,这题需要用树状数组做,先离散化,定义数组s1表示当前已经加入的数,数组s2表示当前加入的数的先前的s1之和,从后往前加入每个数,因为满足题意的数一定是大于前面的某个数,所以当加入到s1时找到前面的s1之和,即为有多少比该数小的数,将个数赋值为s2的该数的值,此时统计比该数小的数的s2值之和,将该和累加到答案中,具体可以举例感受。

代码:

#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define ll long long
#define ull unsigned __int64
const ll INF = 1e18;
const int inf=0x3f3f3f3f;
const int M=100010;
const int N=1000100;
const int MOD=100000;
const double eps=1e-10;
const double pi=acos(-1.0);
using namespace std;

int n;
int a[N],t[N];
ll s1[N],s2[N];

void add(ll *s,int x,int v)
{
    for(int i=x;i<=n;i+=i&(-i))
        s[i]+=v;
}
ll query(ll *s,int x)
{
    ll ans=0;
    for(int i=x;i;i-=i&(-i))
        ans+=s[i];
    return ans;
}

int main()
{
    int i;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        t[i]=a[i];
    }
    sort(t+1,t+1+n);
    int m=unique(t+1,t+1+n)-t-1;
    for(i=1;i<=n;i++)
        a[i]=lower_bound(t+1,t+1+n,a[i])-t;
    add(s1,a[n],1);
    ll ans=0,sum=0;
    for(i=n-1;i>0;i--)
    {
        sum=query(s1,a[i]-1);
        add(s1,a[i],1);
        add(s2,a[i],sum);
        ans+=query(s2,a[i]-1);
    }
    printf("%I64d\n",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值