题目描述:

Problem 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 power of the subarray the sum of products Ks·Ks·s for every positive integer s. The sum contains only finite number of nonzero summands as the number of different values in the array is indeed finite.

You should calculate the power of t given subarrays.
Input

First line contains two integers n and t (1 ≤ n, t ≤ 200000) — the array length and the number of queries correspondingly.

Second line contains n positive integers ai (1 ≤ ai ≤ 106) — the elements of the array.

Next t lines contain two positive integers l, r (1 ≤ l ≤ r ≤ n) each — the indices of the left and the right ends of the corresponding subarray.
Output

Output t lines, the i-th line of the output should contain single positive integer — the power of the i-th query subarray.

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preferred to use cout stream (also you may use %I64d).
Examples

Input

3 2
1 2 1
1 2
1 3

Output

3
6

Input

8 3
1 1 2 2 1 3 1 1
2 7
1 6
2 7

Output

20
20
20
Note

Consider the following array (see the second sample) and its [2, 7] subarray (elements of the subarray are colored):

Then K1 = 3, K2 = 2, K3 = 1, so the power is equal to 32·1 + 22·2 + 12·3 = 20.

思路:

题目是要求给定一个区间,分别统计出区间不同数字的个数,对每个不同的数,求出现次数的平方与该数字的乘积的和。

因为给了好几组区间,很容易想到是一种直接暴力的算法,每个询问都统计一次然后算出一个ans来,但很显然这个算法会超时,因为对于不同的询问区间可能会有一部分重合的以求得的信息,每次暴力计算并没有利用这些已知信息。那么如何使用呢?想到既然是区间问题那不如用线段树来维护一个区间,但是,对于蒟蒻来说,我会做的线段树只能维护一些简单的信息,不会维护这种复杂的统计信息(我还是太菜了),怎么办呢?要知道,维护区间信息问题还有一种重要且巧妙的方法——莫队算法。

哈哈哈,知道了这个算法,虽然也是暴力算法,但是它通过分块+排序预处理能把复杂度降到O(n*sqrt(n)),就可以做了。注意在处理ans是改动一下就好

小心的是,如果用的分组方法是这种:就千万小心把belong数组开大一点,(两倍就行),因为它是刚好分成size*bulk,这么多元素,如果测试点是2e5(对这道题而言),那么最后belong原来的空间用完后会继续往下面的位置赋值,导致越界。(我在这卡了好久qwq)。还有cnt统计个数数组不能开long long。

1     for(int i = 1;i<=bulk;i++)
2     {
3         for(int j = (i-1)*size+1;j<=i*size;j++)
4         {
5             belong[j] = i;
6         }
7     }

(bulk是块数,size是每块的大小)

当然,下面这种分组方式就不存在问题,因为他刚好分n个元素。

1 for(int i = 1;i<=n;i++)
2 scanf("%d",&col[i]),Be[i]=i/unit+1;

卡常技巧:

cmp函数改为莫队玄学奇偶性排序(代码中的cmp2),实际上可以帮你每个点平均优化200ms(可怕)

如果允许,吸氧也是极好的#pragma GCC optimize(2)

优化结果:

第一个为什么都不做(超时)

第二个为改cmp

第三个为改cmp+开optimize(2)

代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cmath>
 4 #define max_n 200005
 5 using namespace std;
 6 int a[max_n];
 7 int cnt[1000005];
 8 int belong[max_n*2];
 9 int bulk;
10 int size;
11 long long ans = 0;
12 long long sum[max_n];
13 int n;
14 int m;
15 struct node
16 {
17     int r;
18     int l;
19     int id;
20 }q[max_n];
21 int cmp(node a,node b)
22 {
23     return (belong[a.l]==belong[b.l])?a.r<b.r:a.l<b.l;
24 }
25 int cmp2(node a,node b)
26 {
27     return (belong[a.l]^belong[b.l])?(a.l<b.l):(belong[a.l]&1)?a.r<b.r:a.r>b.r;
28 }
29
30 void add(int pos)
31 {
32     ans -= (long long)a[pos]*cnt[a[pos]]*cnt[a[pos]];
33     /*if(cnt[a[pos]]==0)
34     {
35         ans++;
36     }*/
37     cnt[a[pos]]++;
38     ans += (long long)a[pos]*cnt[a[pos]]*cnt[a[pos]];
39 }
40 void del(int pos)
41 {
42     ans -= (long long)a[pos]*cnt[a[pos]]*cnt[a[pos]];
43     cnt[a[pos]]--;
44     /*if(cnt[a[pos]]==0)
45     {
46         ans--;
47     }*/
48     ans += (long long)a[pos]*cnt[a[pos]]*cnt[a[pos]];
49 }
50 #pragma GCC optimize(2)
51 int main()
52 {
53     cin >> n >> m;
54     size = sqrt((double)n);
55     bulk = ceil((double)n/size);
56     for(int i = 1;i<=bulk;i++)
57     {
58         for(int j = (i-1)*size;j<=i*size;j++)
59         {
60             belong[j] = i;
61         }
62     }
63     for(int i = 1;i<=n;i++)
64     {
65         cin >> a[i];
66     }
67
68     for(int i = 1;i<=m;i++)
69     {
70         cin >> q[i].l >> q[i].r;
71         q[i].id = i;
72     }
73     sort(q+1,q+m+1,cmp2);
74     /*for(int i = 0;i<n;i++)
75     {
76         cout << belong[i] << " ";
77     }
78     cout << endl;*/
79     int l = 1;
80     int r = 0;
81     for(int i = 1;i<=m;i++)
82     {
83         int nl = q[i].l;
84         int nr = q[i].r;
85         while(l>nl) add(--l);
86         while(r<nr) add(++r);
87         while(l<nl) del(l++);
88         while(r>nr) del(r--);
89         //cout << q[i].id << endl;
90         sum[q[i].id] = ans;
91     }
92     for(int i = 1;i<=m;i++)
93     {
94         cout << sum[i] << endl;
95     }
96     return 0;
97 }

参考文章:

hzwer,「分块」数列分块入门1 – 9 by hzwer,http://hzwer.com/8053.html(分块算法)

WAMonster,莫队算法——从入门到黑题,https://www.cnblogs.com/WAMonster/p/10118934.html(莫队算法良心讲解)

大米饼,莫队算法,https://www.cnblogs.com/Paul-Guderian/p/6933799.html(莫队算法清晰简明讲解)

(两篇结合互补食用效果为佳)

转载于:https://www.cnblogs.com/zhanhonhao/p/11224475.html

Codeforces D. Powerful array(莫队)相关推荐

  1. CodeForces - 86D Powerful array(莫队)

    题目链接:点击查看 题目大意:给出一个由n个数字组成的数列,再给出m次查询,每次查询要求输出[l,r]中的答案,这个题目的答案为: 假设x为区间[l,r]内的数,出现的次数记为cnt[x],则数x的贡 ...

  2. CodeForces 86 D Powerful array 莫队

    Powerful array 题意:求区间[l, r] 内的数的出现次数的平方 * 该数字. 题解:莫队离线操作, 然后加减位置的时候直接修改答案就好了. 这个题目中发现了一个很神奇的事情,本来数组开 ...

  3. cf D. Powerful array 莫队算法

    D. Powerful array 题意:给定一个序列>>每次查询一个区间>>查询该区间内 出现过的数字*出现的次数的平方 的和 思路:学习莫队的第一题或者说小z的袜子是第一题 ...

  4. Yandex.Algorithm 2011 Round 2 D. Powerful array 莫队

    题目链接:点击传送 D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input ...

  5. Yandex.Algorithm 2011 Round 2 D. Powerful array 莫队算法

    链接: http://codeforces.com/problemset/problem/86/D 题意: 给你一个数组,每次询问一个区间,求对于每个数,算出这个数在这个区间出现的个数的平方再*这个数 ...

  6. 【打CF,学算法——四星级】CodeForces 86D Powerful array (莫队算法)

    [CF简介] 题目链接:CF 86D 题面: D. Powerful array time limit per test 5 seconds memory limit per test 256 meg ...

  7. 莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】

    一.理解 我的理解就是巧妙的暴力,利用双指针以及分块思想,巧妙的移动双指针,时间复杂度可以达到O(NlogN). 强推博客:写的又好又全.链接 二.套路 1.普通莫队 [1]核心代码 bool cmp ...

  8. Powerful array CodeForces - 86D (莫队算法)

    An array of positive integers a1, a2, ..., an is given. Let us consider its arbitrary subarray al, a ...

  9. Codeforces 375D - Tree and Queries(dfs序+莫队)

    题目链接:http://codeforces.com/contest/351/problem/D 题目大意:n个数,col[i]对应第i个数的颜色,并给你他们之间的树形关系(以1为根),有m次询问,每 ...

最新文章

  1. 如何在centos7下tomcat中安装https
  2. 一文学会Maven的版本发布
  3. Java实现自定义队列和树结构_Java数据结构之链表、栈、队列、树的实现方法示例...
  4. ajax数据传送中文乱码,springmvc 发送ajax出现中文乱码的解决方法汇总
  5. CentOS6.9中使用yum install时提示:Cannot find a valid baseurl for repo: centos-sclo-rh
  6. how to find element's document section
  7. AI单挑Dota 2世界冠军:被电脑虐哭……
  8. strcpy用于调用的参数太少_JVM:虚拟机方法调用(理解重载和重写的本质)
  9. 文泉驿正黑 font JAVA,字体 | 免费可商用字体~文泉驿正黑体
  10. MariaDB ColumnStore初探(1):安装、使用及测试
  11. Android音视频开发:AudioRecord录制音频
  12. 台式电脑如何使用无线网,wifi怎么连接?
  13. springMVC源码之组件介绍
  14. hive异常 return code X from org.apache.hadoop.hive.ql.exec.mr.MapredLocalTask 解决
  15. 全球及中国液压机行业应用范围调研及投资策略预测报告2022-2028年
  16. 中国计算机科学实验室,上海交通大学计算机科学与工程系(CSE)
  17. 使用nacos配置dubbo3
  18. 云计算提供商锁定的影响以及解决方案
  19. 使用ImageJ批量处理图像 超好用持续更新常用操作
  20. Autoware学习笔记waypoint_follower之twist_filter

热门文章

  1. 我如何从月薪1800到年薪百万到自由职业?
  2. 如何写出和阿里大佬一样高效优雅的打码
  3. discuz!代码内置颜色大全(收藏)
  4. Shoprxr 开源电商系统
  5. ps安装程序检测到计算机重启过程,photoshop cs6安装过程中安装程序遇到错误:请重启计算机,解决办法...
  6. 安卓zip解压软件_压缩软件哪家强?
  7. A trip to InterSpeech2012 (Part II)
  8. 应用zigbee实现智能家居项目
  9. 太实用了!Python竟然能把“长的”变成“短的”!
  10. 无需兑换码下载来自设备制造商的 HEVC 视频扩展