区间求和【莫队板子题】牛客小白月赛17

题目:给你n个数,每个数为ai​,现在有m个询问,每个询问l,r,需要求出:\sum_{i=l}^r a_i*num(a_i)代表ai​在这个区间中出现的次数。

题目链接:https://ac.nowcoder.com/acm/contest/1085/G

输入:

10 5
1 3 2 4 5 6 4 5 6 7
1 5
2 5
3 4
1 10
3 7

 

输出:

15
14
6
73
29

参考博客:1.https://www.cnblogs.com/MisakaAzusa/p/8684319.html

     2.https://www.cnblogs.com/WAMonster/p/10118934.html

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 #define int long long
 5 #define N 100020
 6 int belong[N];
 7 int arr[N];
 8 int sum[N];
 9 int vis[N];
10 int res;
11 int B;
12 struct str{
13     int l,r,id;
14     bool operator<(const str &c)const
15     {
16         return  l/B==c.l/B?r<c.r:l<c.l;
17     }
18 }st[N];
19 void add(int pos) {
20     res-=vis[pos]*vis[pos]*pos;
21     vis[pos]++;
22     res+=vis[pos]*vis[pos]*pos;
23 }
24 void del(int pos) {
25     res-=vis[pos]*vis[pos]*pos;
26     vis[pos]--;
27     res+=vis[pos]*vis[pos]*pos;
28 }
29 signed main(){
30     int n,m;
31     scanf("%lld%lld",&n,&m);
32     B = sqrt(n);
33     
34     for(int i=1;i<=n;i++)
35         scanf("%lld",&arr[i]);
36     for(int i=1;i<=m;i++){
37         int l,r;
38         scanf("%lld%lld",&l,&r);
39         st[i].l=l;
40         st[i].r=r;
41         st[i].id=i;
42     }
43     sort(st+1,st+1+m);
44     res=0;
45     int l=1;
46     int r=0; 
47     for(int i=1;i<=m;i++){
48         int ql=st[i].l;
49         int qr=st[i].r;
50         while(l < ql) del(arr[l++]);
51         while(l > ql) add(arr[--l]);
52         while(r < qr) add(arr[++r]);
53         while(r > qr) del(arr[r--]);
54         sum[st[i].id]=res;
55     }
56     for(int i=1;i<=m;i++){
57         printf("%lld\n",sum[i]);
58     }
59     return 0;
60 } 

 

posted @ 2019-09-18 11:29  pengge666  阅读(231)  评论(0编辑  收藏  举报