D. Powerful array

D. Powerful array

题意

给定一个数列:a[i] (1<= i <= n) K[j]表示 在区间 [l,r]中j出现的次数。有t个查询,每个查询l,r,对区间内所有a[i],求sigma(K[a[i]] * K[a[i]] * a[i])。

分析

首先将区间分块,每块sqrt(n)个,先读入所有的查询,对查询进行排序:先按块序号从小到大,再按右端点的值从小大到排序。

按顺序读入查询,动态变更区间,以及区间的值。如果某个点出现了 x 次,出现 x + 1 次时,区间内增加(2 * x + 1) 。

跑了3000多ms,果然很暴力。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 5;
const int MAXT = 2e5 + 10;
ll a[MAXN];
ll cnt[MAXN];
ll ans[MAXT];
int L, R;
ll res;
struct node
{
    int l, r, bid, id;
    bool operator < (const node &other) const
    {
        if(other.bid == bid) return r < other.r;
        return bid < other.bid;
    }
}q[MAXT];

void query(int l, int r, int is)
{
    if(is)
    {
        for(int i = l; i < L; i++)
        {
            res += ((cnt[a[i]] << 1) + 1) * a[i];
            cnt[a[i]]++;
        }
        for(int i = R + 1; i <= r; i++)
        {
            res += ((cnt[a[i]] << 1) + 1) * a[i];
            cnt[a[i]]++;
        }
        for(int i = L; i < l; i++)
        {
            cnt[a[i]]--;
            res -= ((cnt[a[i]] << 1) + 1) * a[i];
        }
        for(int i = r + 1; i <= R; i++)
        {
            cnt[a[i]]--;
            res -= ((cnt[a[i]] << 1) + 1) * a[i];
        }
    }
    else
    {
        for(int i = l; i <= r; i++)
        {
            res += ((cnt[a[i]] << 1) + 1) * a[i];
            cnt[a[i]]++;
        }
    }
    L = l; R = r;
    ans[q[is].id] = res;
}

int main()
{
    int n, t;
    scanf("%d%d", &n, &t);
    int bsize = sqrt(n + 1);
    for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
    for(int i = 0; i < t; i++)
    {
        scanf("%I64d%I64d", &q[i].l, &q[i].r);
        q[i].bid = q[i].l / bsize;
        q[i].id = i;
    }
    sort(q, q + t);
    for(int i = 0; i < t; i++) query(q[i].l, q[i].r, i);
    for(int i = 0; i < t; i++) printf("%I64d
", ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/ftae/p/6791370.html