zoukankan      html  css  js  c++  java
  • BZOJ3781:小B的询问——题解

    https://www.luogu.org/problemnew/show/2709

    http://www.lydsy.com/JudgeOnline/problem.php?id=3781

    题目描述

    小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

    ————————————————————————————————————————————-

    莫队裸题。

    (以及虽然是裸题但是特别反感题解千篇一律的写“不解释”三个字……那还叫啥子题解啊,直接叫抄板子得了。)

    (也是,可能大佬们本身就瞧不上我这种弱鸡……)

    推荐这个人的博客,找了半天唯一给解释的:https://www.cnblogs.com/CQzhangyu/p/6803872.html

    我们首先想我们要求的是c*c,如果c+1的话就变成了(c+1)*(c+1)=c*c+2c+1,也就是相当于比原答案多加了2*c+1

    同理减的时候就是多减了2*c-1.

    剩下的就是莫队操作了。

    #include<cstdio>
    #include<queue>
    #include<cctype>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=50001;
    inline ll read(){
        ll X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct qu{
        int pos,l,r;
    }q[N];
    int a[N],cnt[N],sum,n,m,k,s;
    ll ans[N];
    inline int bel(int x){return (x-1)/s+1;}
    bool cmp(qu b,qu c){
        return bel(b.l)==bel(c.l)?b.r<c.r:b.l<c.l;
    }
    inline void add(int x){
        sum+=2*cnt[x]+1; 
        cnt[x]++;
        return;
    }
    inline void del(int x){
        sum-=2*cnt[x]-1;
        cnt[x]--;
        return;
    }
    int main(){
        n=read();m=read();k=read();
        s=sqrt(n);
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<=m;i++){
        q[i].pos=i;
        q[i].l=read();
        q[i].r=read();
        }
        sort(q+1,q+m+1,cmp);
        int ql=1,qr=0;
        for(int i=1;i<=m;i++){
        while(ql<q[i].l)del(a[ql++]);
        while(ql>q[i].l)add(a[--ql]);
        while(qr<q[i].r)add(a[++qr]);
        while(qr>q[i].r)del(a[qr--]);
        ans[q[i].pos]=sum;
        }
        for(int i=1;i<=m;i++)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    MySQL数据库----数据类型
    MySQL数据库----安装
    I2c串行总线组成及其工作原理
    感慨
    液晶操作
    串口通信
    9.19AD和DA操作
    9.19键盘的应用
    9.17键盘的操作
    9.15学习笔记
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8190971.html
Copyright © 2011-2022 走看看