题目描述

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

输入

第一行,一个数字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的最大值

输出

对于每组询问,输出一行一个数字,表示答案

样例输入

5
1 1 1 1 1
2
1 2 3 4
1 1 4 4

样例输出

4
1


题解

莫队算法

(为了方便,以下使用$S_x(l,r)$代替$get(l,r,x)$)

题目一眼莫队,不过由于一个询问有4个参数,不能直接处理。

考虑将询问拆成前缀相减的形式,即:

$\ \ \ \ \sum\limits_xS_x(l_1,r_1)·S_x(l_2,r_2)\\=\sum\limits_{x}(S_x(1,r_1)-S_x(1,l_1-1))·(S_x(1,r_2)-S_x(1,l_2-1))\\=\sum\limits_{x}(S_x(1,r_1)·S_x(1,r_2)-S_x(1,l_1-1)·S_x(1,r_2)--S_x(1,r_1)·S_x(1,l_2-1)+S_x(1,l_1-1)·S_x(1,l_2-1))\\=Q(r_1,r_2)-Q(l_1-1,r_2)-Q(r_1,l_2-1)+Q(l_1-1,l_2-1)$

其中:

$Q(a,b)=\sum\limits_{x}S_x(1,a)·S_x(1,b)$

于是就可以把每个询问拆成4个,使用莫队算法分别计算对每个答案的贡献即可。

注意当$a$或$b$中某一个为0时的情况需要过滤掉,否则会加入不存在的位置导致挂掉。

时间复杂度$O(n\sqrt{4m})$

#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 50010
using namespace std;
typedef long long ll;
int si , v[N] , cl[N] , cr[N] , tot;
ll ans[N];
struct data
{
int l , r , flag , id;
data() {}
data(int a , int b , int c , int d) {l = min(a , b) , r = max(a , b) , flag = c , id = d;}
bool operator<(const data &a)const {return (l - 1) / si == (a.l - 1) / si ? r < a.r : (l - 1) / si < (a.l - 1) / si;}
}a[N << 2];
int main()
{
int n , m , i , x1 , y1 , x2 , y2 , lp = 0 , rp = 0;
ll now = 0;
scanf("%d" , &n) , si = (int)sqrt(n);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &v[i]);
scanf("%d" , &m);
for(i = 1 ; i <= m ; i ++ )
{
scanf("%d%d%d%d" , &x1 , &y1 , &x2 , &y2) , a[++tot] = data(y1 , y2 , 1 , i);
if(x1 > 1) a[++tot] = data(x1 - 1 , y2 , -1 , i);
if(x2 > 1) a[++tot] = data(y1 , x2 - 1 , -1 , i);
if(x1 > 1 && x2 > 1) a[++tot] = data(x1 - 1 , x2 - 1 , 1 , i);
}
sort(a + 1 , a + tot + 1);
for(i = 1 ; i <= tot ; i ++ )
{
while(lp < a[i].l) lp ++ , now += cr[v[lp]] , cl[v[lp]] ++ ;
while(rp < a[i].r) rp ++ , now += cl[v[rp]] , cr[v[rp]] ++ ;
while(lp > a[i].l) cl[v[lp]] -- , now -= cr[v[lp]] , lp -- ;
while(rp > a[i].r) cr[v[rp]] -- , now -= cl[v[rp]] , rp -- ;
ans[a[i].id] += a[i].flag * now;
}
for(i = 1 ; i <= m ; i ++ ) printf("%lld\n" , ans[i]);
return 0;
}

【bzoj5016】[Snoi2017]一个简单的询问 莫队算法的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ5016 Snoi2017一个简单的询问(莫队)

    容易想到区间转化成前缀和.这样每个询问有了二维坐标,莫队即可. #include<iostream> #include<cstdio> #include<cmath> ...

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

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

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

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

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

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

  9. 【bzoj3781】小B的询问 莫队算法

    原文地址:http://www.cnblogs.com/GXZlegend/p/6803821.html 题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L ...

随机推荐

  1. 线程7--GCD的基本使用

    子线程执行延时操作,执行完成后返回主线程更新界面 dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DE ...

  2. 线程2--多线程NSThread

    NSThread三种方式创建子线程 /** * NSThread创建线程方式1 * 1> 先创建初始化线程 * 2> start开启线程 */ -(void)creatNSThread { ...

  3. 零基础学C#算法(零基础学算法——C#版)

    今天本人正在看算法方面的书.作为高中数学忘得差不多的渣渣,实在无力.无奈找了本书,c语言写的,哎.我就把其中代码翻译成C#版好了.此坑能否填平,看我耐性和网络支持条件吧.有生之年能看完的话我会把整个项 ...

  4. Q:链表的中间元素

    问题:如何得到一个链表的中间元素?   相信,这个问题对于刚入门编程的人来说,都不会难,最自然而然的想法是先遍历一遍链表,统计链表中的元素的个数,之后,再走一遍链表,所走的步长为链表长度的一半.这样就 ...

  5. 实习小结(五)--- SSM框架搭建(Maven项目)

    之前分享了一个普通的SSM框架的搭建方法,感觉还是过于老套,现在都流行使用Maven来管理项目,在这分享一个使用Maven搭建的SSM(SpringMVC+Spring+MyBatis) 1.首先ma ...

  6. Linux学习5-初学者注意事项

    1.Linux严格区分大小写     2.Linux中所有内容以文件形式保存,包括硬件 硬盘文件是/dev/sd[a-p] 光盘文件是/dev/sr0等     3.Linux不靠扩展名区分文件类型, ...

  7. CSS关于文本渲染的属性text-rendering

    CSS关于文本渲染的属性text-rendering告诉渲染引擎工作时如何优化显示文本. 浏览器会在渲染速度.易读性(清晰度)和几何精度方面做一个权衡. 我们知道,SVG-可缩放矢量图形(Scalab ...

  8. opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)

    #include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgu ...

  9. 这几个Xocode插件用过一段时间还比较稳定好用,Xcode6兼容,推荐给大家:

    这几个Xocode插件用过一段时间还比较稳定好用,Xcode6兼容,推荐给大家: AdjustFontSize: 快捷调整Xcode字体,https://github.com/zats/AdjustF ...

  10. Android 仿美团网,探索使用ViewPager+GridView实现左右滑动查看更多分类的功能

    看下效果图,自己考虑下自己会如何实现,然后再继续看看作者的实现~ 不记得什么时候,我留意到到美团网首页有使用ViewPager+GridView实现左右滑动查看更多分类的一个功能,感觉它很有趣,于是想 ...