• P2709 小B的询问 (莫队板子)


    题目描述

    小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。

    输入输出格式

    输入格式:

    第一行,三个整数N、M、K。

    第二行,N个整数,表示小B的序列。

    接下来的M行,每行两个整数L、R。

    输出格式:

    M行,每行一个整数,其中第i行的整数表示第i个询问的答案。

    输入输出样例

    输入样例#1: 复制
    6 4 3
    1 3 2 1 1 3
    1 4
    2 6
    3 5
    5 6
    输出样例#1: 复制
    6
    9
    5
    2

    说明

    对于全部的数据,1<=N、M、K<=50000

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    const int N=500005;
    
    int n,m,k;
    int a[N],c[N];
    int ans,Ans[N];
    int belong[N];
    struct Querry
    {
        int tim,l,r;
        bool operator < (const Querry &a) const
        {
            if(belong[l]==belong[a.l]) return belong[r]<belong[a.r];
            return belong[l]<belong[a.l];
        }
    }q[N];
    
    int read()
    {
        char c=getchar();int num=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num;
    }
    
    void init()
    {
        n=read(),m=read(),k=read();
        int size=sqrt(n);
        for(int i=1;i<=n;++i)
            a[i]=read(),
            belong[i]=(i-1)/size+1;
        for(int i=1;i<=m;++i)
            q[i].l=read(),q[i].r=read(),q[i].tim=i;
        sort(q+1,q+m+1);
        
    }
    
    /*void update(int now,bool type)
    {
        if(type)
        {
            ans-=c[now]*c[now];
            ++c[now];
            ans+=c[now]*c[now];
        }
        else
        {
            ans-=c[now]*c[now]; 
            --c[now];
            ans+=c[now]*c[now];
        }
    }*/
    void update(int now,bool type)
    {
        if(type)
            ans+=c[now]<<1|1,++c[now];        //(a+1)*(a+1)==a*a+2*a+1,比a*a多了2*a+1 
        else
            ans-=(c[now]<<1)-1,--c[now];    //(a-1)*(a-1)==a*a-2*a+1,比a*a少了2*a-1 
    }
    
    void work()
    {
        for(int i=q[1].l;i<=q[1].r;++i)
            update(a[i],1);
        Ans[q[1].tim]=ans;
        for(int i=2;i<=m;++i)
        {
            if(q[i].l>q[i-1].l)
                for(int j=q[i-1].l;j<q[i].l;++j)
                    update(a[j],0);
            if(q[i].l<q[i-1].l)
                for(int j=q[i].l;j<q[i-1].l;++j)
                    update(a[j],1);
            if(q[i].r<q[i-1].r)
                for(int j=q[i].r+1;j<=q[i-1].r;++j)
                    update(a[j],0);
            if(q[i].r>q[i-1].r)
                for(int j=q[i-1].r+1;j<=q[i].r;++j)
                    update(a[j],1);
            Ans[q[i].tim]=ans;    
        }
        for(int i=1;i<=m;++i)
            printf("%d
    ",Ans[i]);
    }
    
    int main()
    {
        init();
        work();
        return 0;
    }
  • 相关阅读:
    笔记:端子镀金厚度
    笔记:C 编译过程
    抽象类与接口类
    面向对象的三大特性之继承
    类命名空间与对象、实例的命名空间 面向对象的组合用法
    初识类和对象
    面向过程与面向对象
    初识面向对象
    hashlib模块configparser模块logging模块
    collections模块和os模块
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8439741.html
Copyright © 2020-2023  润新知