[Tyvj Jan]1432楼兰图腾(树状数组)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhanghaoxian1/article/details/81909798

[Tyvj Jan]楼兰图腾

题目描述
在完成了分配任务之后,西部314来到了楼兰古城的西部。相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(‘V’),一个部落崇拜铁锹(‘∧’),他们分别用V和∧的形状来代表各自部落的图腾。
西部314在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了N个点,经测量发现这N个点的水平位置和竖直位置是两两不同的。西部314认为这幅壁画所包含的信息与这N个点的相对位置有关,因此不妨设坐标分别为(1,y1),(2,y2),…,(n,yn),其中y1~yn是1到n的一个排列。
西部314打算研究这幅壁画中包含着多少个图腾,其中V图腾的定义如下(注意:图腾的形式只和这三个纵坐标的相对大小排列顺序有关)1<=i

#include <cstdio>
#include <string>
#include <cstring>
#define N 200005
#define ll long long
using namespace std;

ll a[N],c[N],n;
struct arr
{
    ll l,r;
}a1[N],a2[N];

void add(ll x, ll y)
{
    while (x <= n)
    {
        c[x]+=y;
        x+=x&(-x);
    }
}

ll count(ll x)
{
    ll sum = 0;
    while (x > 0)
    {
        sum+=c[x];
        x-=x&(-x);
    }
    return sum;
}

int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++)
    {
        ll s = count(a[i]);
        a1[i].l = s;
        a2[i].l = i - 1 - s;
        add(a[i], 1);
    }
    memset(c, 0, sizeof(c));
    for (int i = n; i >= 1; i--)
    {
        ll s = count(a[i]);
        a1[i].r = s;
        a2[i].r = n - i - s;
        add(a[i], 1);
    }
    ll ans = 0;
    for (int i = 1; i <= n; i++)
        ans+=a2[i].l * a2[i].r;
    printf("%lld ", ans);
    ans = 0;
    for (int i = 1; i <= n; i++)
        ans+=a1[i].l * a1[i].r;
    printf("%lld\n", ans);
}

猜你喜欢

转载自blog.csdn.net/zhanghaoxian1/article/details/81909798