• 区间求和(莫队算法)


    链接:https://ac.nowcoder.com/acm/contest/1085/G
    来源:牛客网

    小sun最近突然对区间来了兴趣,现在他有这样一个问题想问问你:
    给你n个数,每个数为ai,现在有m个询问,每个询问l,r,需要求出:

     链接:https://ac.nowcoder.com/acm/contest/1085/G
    来源:牛客网

    输入描述:

    第一行,两个整数n,m

    第二行,总共n个数,代表这个数列

    接下来m行,每行两个整数l,r,代表一个询问

    输出描述:

    输出总共m行,对于每个询问,输出这个询问对应的答案
    示例1

    输入

    复制
    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

    备注:

    1n,m1e5
    1ai1e5
    1≤l,r≤n
    经典莫队算法:维护区间某个数的出现次数
    但是这个让求的是区间内的ai*num[i]
    如果区间内有两个5就是加上5*2+5*2
    不是简单的加a[i]
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=5e5+100;
    typedef long long ll; 
    int n,m;
    int a[maxn];
    ll ans[maxn];
    int vis[maxn]; 
    struct node{
        int l,r;
        int id;
    }t[maxn];
    int mp[maxn],block,belong[maxn];
    bool cmp(node x,node y){
        if(belong[x.l]!=belong[y.l]){
            return belong[x.l]<belong[y.l];
        }
        else{
            if(belong[x.l]&1){
                return x.r<y.r;
            }
            else{
                return x.r>y.r;
            }
        }
    }
    ll res;
    void remove(int pos){
        res-=1ll*a[pos]*vis[a[pos]]*vis[a[pos]];//先把之前的权值减去在加上之后的权值 
        vis[a[pos]]--; 
        res+=1ll*a[pos]*vis[a[pos]]*vis[a[pos]];
    }
    void add(int pos){
        res-=1ll*a[pos]*vis[a[pos]]*vis[a[pos]]; 
        vis[a[pos]]++; 
        res+=1ll*a[pos]*vis[a[pos]]*vis[a[pos]];
    }
    int main(){
        scanf("%d%d",&n,&m);
        block=sqrt(n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            belong[i]=(i-1)/block+1;
            
        }//分块处理
        for(int i=1;i<=m;i++){
            scanf("%d%d",&t[i].l,&t[i].r);
            t[i].id=i;
        } 
        sort(t+1,t+m+1,cmp);
        int l=1,r=0;
        int ql,qr; 
        for(int i=1;i<=m;i++){
            ql=t[i].l,qr=t[i].r;
            while(l<ql){
                remove(l++);
            } 
            while(l>ql){
                add(--l);
            }
            while(r>qr){
                remove(r--);
            }
            while(r<qr){
                add(++r);
            }
            ans[t[i].id]=res; 
        }
        for(int i=1;i<=m;i++){
            printf("%lld
    ",ans[i]);
        }
        
    }
    
    
    
     
  • 相关阅读:
    第十三周助教小结
    记事本
    第十二周助教小结
    与周老师会谈之后的感想
    第十一周总结
    第十周助教总结
    听周筠老师一席话,受益匪浅
    2020软件工程作业04
    2020软件工程作业02
    2020软件工程作业01
  • 原文地址:https://www.cnblogs.com/lipu123/p/14295351.html
Copyright © 2020-2023  润新知