区间(interval.cpp)

时限:2000ms

空间限制:512MB

【问题描述】

给出一个长度为 n 的序列 a[1]…a[n]。

给出 q 组询问,每组询问形如&lt;x,y&gt;&lt;x,y&gt;<x,y>,求 a 序列的所有区间中,数字 x 的出现次数与数

字 y 的出现次数相同的区间有多少个。

【输入格式】

第一行两个数 n 和 q。

第二行 n 个数 a[i]。

接下来 q 行,每行两个数 x,y 表示一组询问。

【输出格式】

输出 q 行,每行一个数表示对应询问的答案。

【样例输入】

3 2

1 2 1

1 2

4 5

【样例输出】

2

6

【数据规模与约定】

对于 30%的数据:1≤n≤100;1≤q≤1000。

对于另外 30%的数据:序列中只有最多 50 种不同数字且 1≤n≤1000。

对于 100%的数据:1≤n≤8000;1≤q≤500000;1≤x,y,a[i]≤10^9。


这题数据有点吓人,考试时搞了一个多小时发现读错了题就知道自己没救了,匆忙之中写了60分暴力,结果303030分直接RERERE,还有303030分TLETLETLE了,弄得我不知道怎么是好,下来听了听题解,发现其实并没有我想的那么复杂。

那么我们首先要算算效率,如果我们跑个均摊O(n2)O(n^2)O(n2)的算法似乎刚好卡住2s2s2s时限,于是再仔细思考一下,如果我们维护一个xxx和yyy的区间的出现次数的前缀和,显然如果两个前缀和的值相同的话,这两个前缀和之间形成的区间肯定xxx和yyy出现的次数是相同的,这样可以修改答案。但我们再细算一下,对于每次询问,我们要关心的只是xxx和yyy的位置,而其他位置的前缀和显然可以对之前的前缀和进行继承。所以这个地方一个小技巧,我们先将aaa数组离散化,然后用动态数组vectorvectorvector来记录每种数的下标。直接在动态数组中跳下标统计答案就行了。其他细节详见代码。

代码如下

#include<bits/stdc++.h>

//常量
#define N 8005
#define inf 1000000000

using namespace std;

//读入优化
inline long long read(){
	long long ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
	return ans;
}

//变量
int n,sum[N<<1],b[N],a[N],siz,q;
vector<int>pos[N],recycle;
map<int,int>s;

//计算区间个数
inline int cal(int x){return x==0?0:x*(x-1)/2;}

int main(){
	n=read(),q=read();
	for(int i=1;i<=n;++i)b[i]=a[i]=read();

//离散化
	sort(b+1,b+n+1);
	siz=unique(b+1,b+n+1)-b-1;
	for(int i=1;i<=siz;++i)s[b[i]]=i;
	for(int i=1;i<=n;++i)pos[s[a[i]]].push_back(i);

//防止越界
	for(int i=0;i<=siz;++i)pos[i].push_back(n+1);

//询问
	while(q--){
		int x=s[read()],y=s[read()];
		int head1=0,head2=0,last=0,delta=0,ans=0;
		++sum[n];
		while(last!=n){
			if(pos[x][head1]<pos[y][head2]){
				int len=pos[x][head1]-last-1;
				ans+=len*sum[n+delta]+cal(len);
				sum[n+delta]+=len;
				last=pos[x][head1++]-1,recycle.push_back(n+delta),++delta;
			}
			else{
				int len=pos[y][head2]-last-1;
				ans+=len*sum[delta+n]+cal(len);
				sum[delta+n]+=len;
				last=pos[y][head2++]-1,recycle.push_back(n+delta),--delta;
			}
		}
		while(!recycle.empty())sum[recycle.back()]=0,recycle.pop_back();
		cout<<ans<<'\n';
	}
	return 0;
}

2018.06.29 NOIP模拟 区间(前缀和差量)的更多相关文章

  1. 2018.06.29 NOIP模拟 旅馆(线段树)

    旅馆 [问题描述] OIEROIEROIER 们最近的旅游计划,是到长春净月潭,享受那里的湖光山色,以及明 媚的阳光.你作为整个旅游的策划者和负责人,选择在潭边的一家著名的旅馆住 宿.这个巨大的旅馆一 ...

  2. 2018.06.29 NOIP模拟 繁星(前缀和)

    繁星 [问题描述] 要过六一了,大川正在绞尽脑汁想送给小伙伴什么礼物呢.突然想起以前拍过一张夜空中的繁星的照片,这张照片已经被处理成黑白的,也就是说,每个像素只可能是两个颜色之一,白或黑.像素(x,y ...

  3. 2018.06.29 NOIP模拟 Gcd(容斥原理)

    Gcd 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出n个正整数,放入数组 a 里. 问有多少组方案,使得我从 n 个数里取出一个子集,这个子集的 gcd 不为 1 ,然后我再从 ...

  4. 2018.06.29 NOIP模拟 边的处理(分治+dp)

    边的处理(side.cpp) [问题描述] 有一个 n 个点的无向图,给出 m 条边,每条边的信息形如<x,y,c,r><x,y,c,r><x,y,c,r>. 给出 ...

  5. 2018.06.29 NOIP模拟 排列(线段树)

    排列(premu.cpp) [题目描述] 对于一个 1 到 n 的排列,逆序数的定义为:排列中第 i 位 ai的逆序数就是 a1-ai-1中比 ai大的数的个数.另外用 pi表示 a1,-,ai的逆序 ...

  6. 2018.06.29 NOIP模拟 Minimum(最小生成树)

    Minimum 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一幅由 n 个点 m 条边构成的无向带权图. 其中有些点是黑点,另外点是白点. 现在每个白点都要与他距离最近的所有黑 ...

  7. 2018.06.29 NOIP模拟 1807(简单递推)

    1807 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一个由数字('0'-'9')构成的字符串.我们说一个子序列是好的,如果他的每一位都是 1.8.0.7 ,并且这四个数字按照 ...

  8. 2018.06.27 NOIP模拟 节目(支配树+可持久化线段树)

    题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的 ...

  9. 2018.06.26 NOIP模拟 纪念碑(线段树+扫描线)

    题解: 题目背景 SOURCE:NOIP2015−GDZSJNZXSOURCE:NOIP2015-GDZSJNZXSOURCE:NOIP2015−GDZSJNZX(难) 题目描述 2034203420 ...

随机推荐

  1. 事件委托,js中的一种优化方法

    在前端编程中,我们常会遇到一种叫做事件委托的方法. 那么, 什么是事件委托呢? 简单来说,事件就是指onclick,onmouseover,onmouseout等大部分事件,为什么说是大部分后面会提到 ...

  2. python判断unicode是否是汉字,数字,英文,或者其他字符

    下面这个小工具包含了 判断unicode是否是汉字,数字,英文,或者其他字符. 全角符号转半角符号. unicode字符串归一化等工作. 还有一个能处理多音字的汉字转拼音的程序,还在整理中. #!/u ...

  3. nodejs文件操作笔记

    nodejs添加了流的概念,通过流操作文件如行云流水,比早前便利畅快多了. 先来第一个例子,我们建一个stream.js文件,里面内容如下: var fs = require("fs&quo ...

  4. JAVA数组详解

    package com.keke.demo; import java.text.ParseException;import java.text.SimpleDateFormat;import java ...

  5. mysql优化连接数

    很多开发人员都会遇见”MySQL: ERROR 1040: Too many connections”的异常情况,造成这种情况的一种原因是访问量过高,MySQL服务器抗不住,这个时候就要考虑增加从服务 ...

  6. selenium常用的断言

    断言: 验证应用程序的状态是否同期望的一致,常见的断言包括验证页面内容,如标题是否与预期一致,当前的位置是否正确等等 断言常被用的4种模式+5种手段:Assert 断言失败的时候,该测试终止 veri ...

  7. 每月IT摘录201805

    摘录自互联网的前辈心得: 一.技术:0.精通一个淘汰的技术对你没有任何价值.学习的精力有限,更应该花在值得学的技术上.比如网络.操作系统.数据结构.算法1.工作要有定力,更多的应该是关心问题如何更有效 ...

  8. ubuntu下 openvpn客户端的配置

    1.安装openvpn sudo apt-get install openvpn 2.配置openvpn 作为客户端,OpenVPN并没有特定的配置文件,而是由服务器提供方给出一个配置文件.对于认证, ...

  9. python内置函数之attr【反射】

    #Auther Bob#--*--conding:utf-8 --*-- #我们来循序渐进的学习反射 import s1 #阶段1# def run():# url = input("请输入 ...

  10. [leetcode]416. Partition Equal Subset Sum分割数组的和相同子集

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...