Codeforces Beta Round #57 (Div. 2) E. Enemy is weak

题目:http://codeforces.com/problemset/problem/61/E

题意:若一个组数下标 i<j<k以及ai>aj>ak 则为一个弱点,计算一组数据中有几个弱点。

思路:1)使用树状数组,从左到右扫描所有的数,令数组a 表示目前为止 已经考虑过的所有的数num,是否存在一个,存在则a[j]=1,不存在则a[j]=0。在计算一个数前面比它的大   数和后面比它小的数可以计算前缀和和后缀和。

            2)  先从前往后搜索数组,使用数组a1记录每一个数前面比它大的的数的个数,使用数组a2记录每一个数后面比它小的数的个数。当以数n1为中间数是有a1*a2个弱点。

            3)由于数的大小为1 ≤ ai ≤ 109,无法开这么大的数组来记录数是否存在。使用数的离散化,将数列排序,使用数组的下标代表代表数的相对大小。使用二分查找lower_bound来查找原数组n1在已排序数组num在的下标。

*注意:树状数组不能从0开始存!所以可以将所有的数组的开头下标设为1。

CODE;

#include <iostream>
#include <stdio.h>
#include <algorithm>
const int N=1000005;
using namespace std;

int n1[N],num[N],a[N],c[N];
int T;

int lowbit(int xx)
{
    return xx&-xx; //树状数组不能从0开始存
}
void add(int x,int d)
{
    while(x<=T)
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
bool cmp(int a,int b)
{
    return a<b;
}
long long a1[N],a2[N];
int main()
{
    //freopen("in.in","r",stdin);

    while(~scanf("%d",&T))
    {
        fill(a,a+T+1,0);
        fill(c,c+T+1,0);
        for(int i=1;i<=T;i++)
        {
            scanf("%d",&n1[i]);
            num[i]=n1[i];
        }
        sort(num+1,num+T+1,cmp);
        long long ans=0;
        for(int i=1;i<=T;i++)
        {
            int k=lower_bound(num,num+T+1,n1[i])-num;
            a[k]=1;
            add(k,1);
            a1[i]=sum(T)-sum(k);
        }

        fill(a,a+T+1,0);
        fill(c,c+T+1,0);
        for(int i=T;i>=1;i--)
        {
            int k=lower_bound(num,num+T+1,n1[i])-num;
            a[k]=1;
            add(k,1);
            a2[i]=sum(k-1);
        }
        for(int i=1;i<=T;i++)
            ans+=a1[i]*a2[i];
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值