• 洛谷 P2709 小B的询问 【莫队】


    洛谷 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

    题解:

    这题就是在莫队入门题上做了一点修改。

    前面的分块、排序、指针 l,r 的移动没变,变的是更新状态这一部分:

    1 void revise(int x,int w)
    2 {
    3     if (w>0) sum+=2*num[a[x]]+1;
    4     if (w<0) sum-=2*num[a[x]]-1;
    5     num[a[x]]+=w;
    6 }

    设 i 在此段中的数量为 x ,若是新增一个 i ,则根据公式可推出:ans+=(x+1)^2-x^2 ==> 2x+1

    若是减少一个 i ,根据公式可推出:ans-=x^2-(x-1)^2 ==> 2x-1

    还要注意一个非常重要的细节(所有的莫队题目都要注意!!!我在这个地方卡了超长时间,终于调出来了), 一开始的指针 l 和 r 初始化要注意, l=1, r=0

    这个要切记,不然就会WA(因为 l=0 的话就会把下标为 -1 的这个点算上去)。

    废话不多说,上代码:

     1 #include<bits/stdc++.h>
     2 #define ll long long 
     3 using namespace std;
     4 const int N=50005;
     5 ll n,m,k,a[N],sum,num[N],block,belong[N],ans[N];
     6 struct node{
     7     int l,r,id;
     8 }q[N];
     9 inline ll read()
    10 {
    11     ll x=0,f=1; char ch=getchar();
    12     while (!isdigit(ch))
    13       f=(ch=='-')?-f:f,ch=getchar();
    14     while (isdigit(ch))
    15       x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    16     return x*f;
    17 }
    18 bool cmp(node a,node b)
    19 {
    20     return belong[a.l]==belong[b.l]?a.r<b.r:belong[a.l]<belong[b.l];
    21 }
    22 inline ll sqr(int x)
    23 {
    24     return x*x;
    25 }
    26 void revise(int x,int w)
    27 {
    28     ///*
    29     if (w>0) sum+=2*num[a[x]]+1;
    30     if (w<0) sum-=2*num[a[x]]-1;
    31     num[a[x]]+=w;
    32     //*/
    33     /*
    34     num[a[x]]+=w;
    35     if (w>0) sum+=2*num[a[x]]-1;
    36     if (w<0) sum-=2*num[a[x]]+1;
    37     */
    38     /*if (w>0) sum+=num[a[x]]<<1|1,num[a[x]]+=w;
    39     if (w<0) num[a[x]]+=w,sum-=num[a[x]]<<1|1;
    40     //num[a[x]]+=w; 
    41     */
    42     
    43 }
    44 int main()
    45 {
    46     n=read(),m=read(),k=read();
    47     block=sqrt(n);
    48     for (int i=1; i<=n; i++)
    49     {
    50         a[i]=read(); belong[i]=i/block+1;
    51     }
    52     for (int i=1; i<=m; i++)
    53     {
    54         q[i].l=read(),q[i].r=read(),q[i].id=i;
    55     }
    56     sort(q+1,q+1+m,cmp);
    57     int zl=1,zr=0; sum=0;
    58     memset(num,0,sizeof(num));
    59     for (int i=1; i<=m; i++)
    60     {
    61         while (zl<q[i].l) revise(zl,-1),zl++;
    62         while (zl>q[i].l) revise(zl-1,1),zl--;
    63         while (zr<q[i].r) revise(zr+1,1),zr++;
    64         while (zr>q[i].r) revise(zr,-1),zr--;
    65         ans[q[i].id]=sum;
    66     }
    67     for (int i=1; i<=m; i++)
    68     {
    69         printf("%lld
    ",ans[i]);
    70     }
    71     return 0;
    72 }
    View Code

    加油加油加油!!! fighting fighting fighting !!!

  • 相关阅读:
    Java类型转换.
    搭建jenkins集群node结点
    java Lambda
    @Autowired使用说明
    Disruptor底层实现讲解与RingBuffer数据结构讲解
    Disruptor并发框架简介
    并发编程中的读写锁分离锁的使用
    并发编程过程中的重入锁
    互联网进行限流策略的Semaphore信号量使用
    并发编程中Future和Callable使用
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9168944.html
Copyright © 2020-2023  润新知