zoukankan      html  css  js  c++  java
  • 洛谷 P2709 BZOJ 3781 小B的询问

    题目描述

    小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求$sum_1^Kc_i^2$的值,其中$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

    吐槽

      BZOJ居然把这题设成权限题,我们这种穷人做不起啊,放个题号吧。

      我的代码在洛谷上跑的挺快,刚开始没开O2,跑了1900+ms,然后去大牛分站交了一波,瞬间540毫秒,rank3了啊!估计我的程序最大的耗时处在两个sort上,algorithm里的东西和STL里的东西缺氧,吸了氧就跑得飞快,几乎是缺氧时的四倍速度了。

      后来加快读、乘法换成位运算、另开一个数组$O(m)$记录答案而不是第二次排序,尤其是最后一项,整整少了60ms,终于卡到了473ms,目前的洛谷rank1.

    解题思路

      一道裸的莫队。莫队的原理可以看我这篇博文,每个莫队题目最重要的步骤都是推导出区间中减少一个元素或加入一个元素后答案的变化。

      这题推公式不难。设当前区间$[l,r]$的答案为$t$,那么增加(l--或r++)一个元素时,设增加元素的颜色为k (l-1或r+1),$f(k)$为题目中的$c(k)$,那么$t+=(f(k)+1)^2-f^2(k)=2*f(k)+1$,同理,减少一个颜色为k的元素时$t-=f^2(k)-(f(k)-1)^2=2*f(k)-1$,于是就套上莫队的标志“四个while”吧。

    源代码

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    inline int get()
    {
        char c;short f = 1; int res = 0;
        while (( (c=getchar())<48||c>57) && c!= '-');
         if (c=='-') f = -1;
          else res = c- '0';
        while ( (c = getchar()) >= 48 && c <= 57)
         res = res * 10 + c -'0';
        return f *res;
    }
    
    int n,m,k;
    int c[50010]={0};
    int f[50010]={0};
    
    struct query{
        int id,pos,l,r,ans;
    }a[50010];
    int aa[50010]={0};
    inline int cmp1(const query & a,const query & b)
    {
        return a.pos==b.pos?a.r<b.r:a.pos<b.pos;
    }
    int main()
    {
        n=get(),m=get(),k=get();
        for(int i=1;i<=n;i++)
            c[i]=get();
        for(int i=1,l,r,kuai=sqrt(n);i<=m;i++)
        {
            l=get();
            r=get();
            a[i]={i,l/kuai,l,r,0};
        }
        sort(a+1,a+1+m,cmp1);
        for(int i=1,l=0,r=0,t=0;i<=m;i++)
        {
            while(r<a[i].r)
            {
                r+=1;
                t+=(f[c[r]]<<1)+1;
                f[c[r]]+=1;
            }
            while(l<a[i].l)
            {
                t-=(f[c[l]]<<1)-1;
                f[c[l]]--;
                l++;
            }
            while(l>a[i].l)
            {
                l--;
                t+=(f[c[l]]<<1)+1;
                f[c[l]]++;
            }
            while(r>a[i].r)
            {
                t-=(f[c[r]]<<1)-1;
                f[c[r]]--;
                r--;
            }
            a[i].ans=t;
        }
        for(int i=1;i<=m;i++) aa[a[i].id]=a[i].ans-1;
        for(int i=1;i<=m;i++) printf("%d
    ",aa[i]);
        return 0;
    }
  • 相关阅读:
    C# — WinForm TCP连接之服务器端
    Linq to SQL — Group by
    pytorch model()[] 模型对象类型
    git官网下载太慢解决方法
    财务分析
    python错题集
    SQL 开窗函数 头尾函数 first_value()/last value()不常用
    徐杨老师的公开课关于敏捷算法
    SQL 开窗函数:range和rows的区别
    SQL开窗函数 row_number(),dense_rank(), rank()
  • 原文地址:https://www.cnblogs.com/wawcac-blog/p/7041597.html
Copyright © 2011-2022 走看看