【分块】Codeforces 86d Powerful array

通道

题意:询问[l,r]区间的权和,权定义为sum(k^2*a[i]),k表示a[i]出现的次数

思路:区间每增加一个a[i],增量是(2*x+1)*a[i],因为(x+1)^2*a[i] = (x^2 +2*x + 1)*a[i]

分块排序即可,块内按r排序

代码:

#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

#define N 200100
typedef long long ll;

ll a[N], cnt[N*5], ans[N], res;
int L, R;

struct node {
    int x, y, l, p;
} q[N];
bool cmp(const node &x, const node &y) {
    if (x.l == y.l) return x.y < y.y;
    return x.l < y.l;
}
void query(int x, int y, int flag) {
    if (flag) {
        for (int i=x; i<L; i++) {
            res += ((cnt[a[i]]<<1)+1)*a[i];
            cnt[a[i]]++;
        }
        for (int i=R+1; i<=y; i++) {
            res += ((cnt[a[i]]<<1)+1)*a[i];
            cnt[a[i]]++;
        }
        for (int i=L; i<x; i++) {
            cnt[a[i]]--;
            res -= ((cnt[a[i]]<<1)+1)*a[i];
        }
        for (int i=y+1; i<=R; i++) {
            cnt[a[i]]--;
            res -= ((cnt[a[i]]<<1)+1)*a[i];
        }
    } else {
        for (int i=x; i<=y; i++) {
            res += ((cnt[a[i]]<<1)+1)*a[i];
            cnt[a[i]]++;
        }
    }
    L = x, R = y;
}
int main() {
    int n, t;
    scanf("%d%d", &n, &t);
    for (int i=1; i<=n; i++) scanf("%I64d", &a[i]);
    int block_size = sqrt(n);
    for (int i=0; i<t; i++) {
        scanf("%d%d", &q[i].x, &q[i].y);
        q[i].l = q[i].x / block_size;
        q[i].p = i;
    }
    sort(q, q+t, cmp);
    for (int i=0; i<t; i++) {
        query(q[i].x, q[i].y, i);
        ans[q[i].p] = res;
    }
    for (int i=0; i<t; i++) printf("%I64d\n", ans[i]);
    return 0;
}

时间: 2024-11-09 12:32:26

【分块】Codeforces 86d Powerful array的相关文章

Codeforces#86D Powerful array(分块暴力)

Description An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?≤?l?≤?r?≤?n. For every positive integer s denote by Ks the number of occurrences of s into the subarray. We call the

Codeforces 86D Powerful array(莫队)

题目链接:http://codeforces.com/problemset/problem/86/D 题目: An array of positive integers a1, a2, ..., an is given. Let us consider its arbitrary subarray al, al + 1..., ar, where 1 ≤ l ≤ r ≤ n. For every positive integer s denote by Ks the number of occu

CodeForces 86D Powerful array(莫队算法)

和BZOJ2038差不多..复习一下. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 int block; 6 struct Query{ 7 int i,l,r; 8 bool operator<(const Query &q)const{ 9 if(l/block==q.l/block) return r<q.r; 10 re

CodeForces - 86D Powerful array (莫队)

题意:查询的是区间内每个数出现次数的平方×该数值的和. 分析:虽然是道莫队裸体,但是姿势不对就会超时.答案可能爆int,所以要开long long 存答案.一开始的维护操作,我先在res里减掉了a[pos]*cnt[a[pos]]*cnt[a[pos]],将cnt[a[pos]]+1,再将乘积加回.其实根据数学原理,K^2和(K+1)^2差值是2K+1,那么其实每次更新时只要加上或减去a[pos]*(2*cnt[pos]+1)即可,这样更高效. #include<bits/stdc++.h>

86D - Powerful array

莫队. 统计ai[i]的出现次数,每一次先还原贡献,再加上或减去当前的贡献即可. #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #i

codeforces 86D D. Powerful array(莫队算法)

题目链接: D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output An array of positive integers a1, a2, ..., an is given. Let us consider its arbitrary subarray al, al + 1..., ar, wh

D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?

CodeForces 86D(Yandex.Algorithm 2011 Round 2)

思路:莫队算法,离线操作,将所有询问的左端点进行分块(分成sqrt(n) 块每块sqrt(n)个),用左端点的块号进行排序小的在前,块号相等的,右端点小的在前面. 这样要是两个相邻的查询在同一块内左端点每次最多移动sqrt(n) n次的话效率为nsqrt(n) ,对于同一块内右端点为有序的那么最多移动 n次  .总的效率为nsqrt(n) . 要是相邻的查询不同块 最坏效率为O(n) 因为块最多为sqrt(n)个那么坏效率也为nsqrt(n).   总的效率就为nsqrt(n) #include

codeforces 482B. Interesting Array【线段树区间更新】

题目:codeforces 482B. Interesting Array 题意:给你一个值n和m中操作,每种操作就是三个数 l ,r,val.就是区间l---r上的与的值为val,最后问你原来的数组是多少?如果不存在输出no 分析:分析发现要满足所有的区间,而一个点上假如有多个区间的话,这个点的值就是所有区间或的值,因为只有这样才能满足所有区间的,把所有位上的1都保存下来了,那么可以发现用线段树来维护,但是那么怎么判断满不满足条件呢?可以也用线段树,更新了之后在整个维护一遍看看满不满足题意,如