Description

给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出
 
get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次。

Input

第一行,一个数字N,表示序列长度。
第二行,N个数字,表示a1~aN
第三行,一个数字Q,表示询问个数。
第4~Q+3行,每行四个数字l1,r1,l2,r2,表示询问。
N,Q≤50000
N1≤ai≤N
1≤l1≤r1≤N
1≤l2≤r2≤N
注意:答案有可能超过int的最大值
 
                         -by bzoj
http://www.lydsy.com/JudgeOnline/problem.php?id=5016


一开始看错了题,以为是每次询问一个x,
然后想直接主席树;
然后很快发现题不会这么简单;
询问两个区间对应颜色出现次数相乘再求和;
两个区间,颜色;
想到离线
把一个有两个区间的询问变成两个有一个区间和一个前缀的询问作差,
然后按前缀端点排序,逐渐右移端点,维护更长的前缀,以更新询问,
这样每次前缀的端点右移时,前缀里只有一个颜色的数量增加了1,
相应的,以后要询问的区间只有这个颜色对答案的贡献增加了区间中这个颜色的个数,
然而这个颜色对答案的贡献取决于询问的区间中有多少这个颜色,
换言之取决于询问哪个区间,
一开始想用什么主席树之类的维护,死活不会,
然后一看时限3S想到分块暴力,
然后发现很科学;
然后就有了这个做法
把询问(l1,r1,l2,r2)拆成(l1,r1,pos=l2-1,-),(l1,r1,pos=r2,+)
表示
询问[l1,r1]与l2-1前缀的结果,并在原询问中减去它
询问[l1,r1]与r2前缀的结果,并在原询问中加上它
将拆成来的询问按pos从小到大排序,
按这样的顺序处理询问可以通过单向右移端点来依次维护所有询问的前缀
查询的时候,采用分块,
被整块查询的块可以直接使用一个块在当前前缀下的答案
维护方法是
在读入数列时对每个块建一个颜色桶MP[]
每右移前缀端点,使颜色col(x)个数在前缀中增加时,把每个块的答案都增加MP[col(x)]
被查询的散点,每个散点对答案的贡献是当前前缀中与这个散点颜色相同的点的个数
可以开个桶,在前缀变长时逐渐更新即可,
复杂度为$O((N+M)\sqrt{N})$
代码:
 #include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int sz,N,Q,num;
int a[];
LL MAP[][],inlineMAP[];
LL ANS[];
struct ss{
int L,R,pos,id;
LL flag;
}qrr[];
LL ans[];
bool cmp(ss a,ss b){
return a.pos<b.pos;
}
LL get(int ,int );
int main()
{
int i,j,k;
scanf("%d",&N);
sz=sqrt(N);
for(i=num=;i<=N;i+=sz,num++){
for(j=i;j<i+sz&&j<=N;j++){
scanf("%d",&a[j]);
MAP[num][a[j]]++;
}
}
num--;
scanf("%d",&Q);
for(i=;i<=Q;i++){
scanf("%d%d%d%d",&qrr[i].L,&qrr[i].R,&qrr[i].pos,&qrr[i+Q].pos);
qrr[i+Q].L=qrr[i].L,qrr[i+Q].R=qrr[i].R;
qrr[i+Q].id=qrr[i].id=i;
qrr[i].flag=-,qrr[i+Q].flag=;
qrr[i].pos--;
}
sort(qrr+,qrr+Q+Q+,cmp);
j=;
for(i=;i<=Q<<;i++){
while(j<qrr[i].pos){
j++;
inlineMAP[a[j]]++;
for(k=;k<=num;k++)
ANS[k]+=MAP[k][a[j]];
}
ans[qrr[i].id]+=qrr[i].flag*get(qrr[i].L,qrr[i].R);
}
for(i=;i<=Q;i++)
printf("%lld\n",ans[i]);
return ;
}
LL get(int L,int R){
LL ret=;
int i,j,k;
int l,r;
if(R-L+<=sz){
for(i=L;i<=R;i++)
ret+=inlineMAP[a[i]];
return ret;
}
for(i=j=;i<L;i+=sz,j++);
l=i-;
for(;i+sz<=R+&&i<=N;j++,i+=sz)
ret+=ANS[j];
r=i;
for(i=L;i<=l;i++)
ret+=inlineMAP[a[i]];
for(i=r;i<=R;i++)
ret+=inlineMAP[a[i]];
return ret;
}

或许有树套树的做法?

bzoj P5016[Snoi2017]一个简单的询问——solution的更多相关文章

  1. bzoj 5016: [Snoi2017]一个简单的询问

    Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次. Input 第 ...

  2. [SNOI2017]一个简单的询问

    [SNOI2017]一个简单的询问 题目大意: 给定一个长度为\(n(n\le50000)\)的序列\(A(1\le A_i\le n)\),定义\(\operatorname{get}(l,r,x) ...

  3. 【BZOJ5016】[Snoi2017]一个简单的询问 莫队

    [BZOJ5016][Snoi2017]一个简单的询问 Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计 ...

  4. Gym101138D Strange Queries/BZOJ5016 SNOI2017 一个简单的询问 莫队、前缀和、容斥

    传送门--Gym 传送门--BZOJ THUWC2019D1T1撞题可还行 以前有些人做过还问过我,但是我没有珍惜,直到进入考场才追悔莫及-- 设\(que_{i,j}\)表示询问\((1,i,1,j ...

  5. BZOJ5016:[SNOI2017]一个简单的询问(莫队)

    Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次. Input 第 ...

  6. [bzoj5016][Snoi2017]一个简单的询问

    来自FallDream的博客,未经允许,请勿转载,谢谢. 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出   get(l,r,x)表示计算区间[l,r]中 ...

  7. [SNOI2017]一个简单的询问【莫队+容斥原理】

    题目大意 给你一个数列,让你求两个区间内各个数出现次数的乘积的和. 分析 数据范围告诉我们可以用莫队过. 我并不知道什么曼哈顿什么乱七八糟的东西,但是我们可以用容斥原理将这个式子展开来. \[\sum ...

  8. 【bzoj5016】[Snoi2017]一个简单的询问 莫队算法

    题目描述 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次. 输入 第一行,一个数字N,表 ...

  9. bzoj5016 & loj2254 [Snoi2017]一个简单的询问 莫队

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5016 https://loj.ac/problem/2254 题解 原式是这样的 \[ \su ...

随机推荐

  1. GPS轨迹数据可视化的三种途径

    有一阵子没写过博客了,最近因为自己小队申请了项目有并且要帮研究生做一些数据处理的小任务,接触到可视化.这里介绍最近学到的了三种方法. 第一种是用python. 这里原理是用matplotlib里面的s ...

  2. rabbitmq系列五 之主题交换机

    1.主题 在前面的例子中,我们对日志系统进行了改进.使用了direct交换机代替了fanout交换机,从只能盲目的广播消息改进为有可能选择性的接收日志. 尽管直接交换机能够改善我们的日志系统,但是它也 ...

  3. javascript数据结构与算法---检索算法(顺序查找、最大最小值、自组织查询)

    javascript数据结构与算法---检索算法(顺序查找.最大最小值.自组织查询) 一.顺序查找法 /* * 顺序查找法 * * 顺序查找法只要从列表的第一个元素开始循环,然后逐个与要查找的数据进行 ...

  4. [每天解决一问题系列 - 0004] Excel 公式中拼接字符串

    问题描述: 之前很少用excel的formula,今天用户发过来一个文件,里边存储了很多字段对应的编号.想把这些生成我想要的格式,然后导入代码中,当然可以使用第三方的excel操作库来做.最简单直接的 ...

  5. oracle exp imp日常使用

    http://www.cnblogs.com/ningvsban/archive/2012/12/22/2829009.html http://www.cnblogs.com/mq0036/archi ...

  6. Python多线程、多进程实现

    劝君莫惜金缕衣,劝君惜取少年时.花开堪折直须折,莫待无花空折枝. 内容摘要: paramiko模块 进程.与线程区别 python GIL全局解释器锁 多线程    语法    join    线程锁 ...

  7. 平衡二叉树-AVL树(LL、RR、LR、RL旋转)

    平衡二叉树的定义: 任意的左右子树高度差的绝对值不超过1,将这样的二叉树称为平衡二叉树,二叉平衡树前提是一个二叉排序树. 平衡二叉树的插入: 二叉平衡树在插入或删除一个结点时,先检查该操作是否导致了树 ...

  8. javascript保留字趣史

    转载自[https://mathiasbynens.be/notes/reserved-keywords](https://mathiasbynens.be/notes/reserved-keywor ...

  9. 【JAVA】序列化

    好处有2: 实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里). 利用序列化实现远程通信,即在网络上传送对象的字节序列. 序列化ID的作用: 简单来说,Java的序列化机制 ...

  10. SpringDataJPA快速入门

    访问我的博客 前言 之前在学习 SpringBoot 框架的时候,使用到了 SpringData JPA,但是当时只是简单的查询,没有用到稍微复杂的查询. JPA 的 JPQL 语法规则对于简单的查询 ...