题目链接

第一道Ynoi

显然每次询问的答案为三个区间的长度和减去公共数字个数*3.

如果是公共数字种数的话就能用莫队+bitset存每个区间的状态,然后3个区间按位与就行了。

但现在是个数,bitset中除了保存每个数是否出现外,还要保存出现的次数。

这时我们发现每个数字的出现次数之和\(=n\)

于是想到离散化以后每个数字占bitset中的一格。

还记得\(SA\)里的基数排序吗?这样就能使第\(n\)次加入区间的同一个数字有固定的位置安放。

于是就能莫队了。

但是一看数据范围,好像开不下\(1e5\)个长度为\(1e5\)的bitset啊。

没关系,把答案分成3组,一组一组来就行了。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
#include <cmath>
#include <iostream>
using namespace std;
const int MAXN = 100010;
const int MAXM = 34010;
bitset <MAXN> ans[MAXM], now;
int n, m, a[MAXN];
inline int read(){
int s = 0;
char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
return s;
}
int Q;
struct lsh{
int val, id;
int operator < (const lsh A) const{
return val < A.val;
}
}p[MAXN];
struct ask{
int l, r, id;
int operator < (const ask A) const{
return l / Q == A.l / Q ? r < A.r : l < A.l;
}
}q[MAXM * 3];
int val[MAXN], cnt, sum[MAXN], v[MAXN], all, Ans[MAXM];
void work(){
sort(q + 1, q + all + 1);
now.reset();
memset(v, 0, sizeof v);
int l = 1, r = 1; now.set(val[1]); v[val[1]] = 1;
for(int i = 1; i <= all; ++i){
while(r < q[i].r){ ++r; now.set(val[r] - v[val[r]]); ++v[val[r]]; }
while(l > q[i].l){ --l; now.set(val[l] - v[val[l]]); ++v[val[l]]; }
while(r > q[i].r){ --v[val[r]]; now.set(val[r] - v[val[r]], 0); --r; }
while(l < q[i].l){ --v[val[l]]; now.set(val[l] - v[val[l]], 0); ++l; }
ans[q[i].id] &= now;
}
}
int main(){
n = read(); m = read(); Q = sqrt(n);
for(int i = 1; i <= n; ++i)
p[i].val = read(), p[i].id = i;
for(int i = 1; i <= 33337; ++i)
ans[i].set();
sort(p + 1, p + n + 1);
for(int i = 1; i <= n; ++i)
if(p[i].val != p[i - 1].val)
val[p[i].id] = ++cnt;
else val[p[i].id] = cnt;
for(int i = 1; i <= n; ++i)
++sum[val[i]];
for(int i = 1; i <= cnt; ++i)
sum[i] += sum[i - 1];
for(int i = 1; i <= n; ++i)
val[i] = sum[val[i]];
int o = m / 3;
if(o){
for(int qqc = 1; qqc <= 2; ++qqc){
cnt = 0;
for(int i = 1; i <= o; ++i){
q[++cnt].id = i; q[cnt].l = read(); q[cnt].r = read(); Ans[i] += q[cnt].r - q[cnt].l + 1;
q[++cnt].id = i; q[cnt].l = read(); q[cnt].r = read(); Ans[i] += q[cnt].r - q[cnt].l + 1;
q[++cnt].id = i; q[cnt].l = read(); q[cnt].r = read(); Ans[i] += q[cnt].r - q[cnt].l + 1;
}
all = o * 3; work();
for(int i = 1; i <= o; ++i){
printf("%d\n", Ans[i] - int(ans[i].count()) * 3);
Ans[i] = 0; ans[i].set();
}
}
}
m -= o * 2; cnt = 0;
for(int i = 1; i <= m; ++i){
q[++cnt].id = i; q[cnt].l = read(); q[cnt].r = read(); Ans[i] += q[cnt].r - q[cnt].l + 1;
q[++cnt].id = i; q[cnt].l = read(); q[cnt].r = read(); Ans[i] += q[cnt].r - q[cnt].l + 1;
q[++cnt].id = i; q[cnt].l = read(); q[cnt].r = read(); Ans[i] += q[cnt].r - q[cnt].l + 1;
}
all = m * 3; work();
for(int i = 1; i <= m; ++i)
printf("%d\n", Ans[i] - int(ans[i].count()) * 3);
return 0;
}

【洛谷 P4688】 [Ynoi2016]掉进兔子洞(bitset,莫队)的更多相关文章

  1. luogu P4688 [Ynoi2016]掉进兔子洞 bitset 莫队

    题目链接 luogu P4688 [Ynoi2016]掉进兔子洞 题解 莫队维护bitset区间交个数 代码 // luogu-judger-enable-o2 #include<cmath&g ...

  2. [洛谷P4688][Ynoi2016]掉进兔子洞

    题目大意:给定一个$n(n\leqslant10^5)$序列,$m(m\leqslant10^5)$个询问,每个询问给出$l_1,r_1,l_2,r_2,l_3,r_3$.令$s$为该三个区间的交集的 ...

  3. 洛谷P4135 Ynoi2016 掉进兔子洞 (带权bitset?/bitset优化莫队 模板) 题解

    题面. 看到这道题,我第一反应就是莫队. 我甚至也猜出了把所有询问的三个区间压到一起处理然后分别计算对应询问答案. 但是,这么复杂的贡献用什么东西存?难道要开一个数组 query_appear_tim ...

  4. Luogu4688 [Ynoi2016]掉进兔子洞 【莫队,bitset】

    题目链接:洛谷 我们知道要求的是\([l_1,r_1],[l_2,r_2],[l_3,r_3]\)的可重集取交的大小,肯定是要用bitset的,那怎么做可重集呢? 那就是要稍微动点手脚,首先在离散化的 ...

  5. bzoj千题计划320:bzoj4939: [Ynoi2016]掉进兔子洞(莫队 + bitset)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4939 ans= r1-l1+1 + r2-l2+1 +r3-l3+1 - ∑ min(cnt1[i ...

  6. BZOJ4939 Ynoi2016掉进兔子洞(莫队+bitset)

    容易发现要求三个区间各数出现次数的最小值.考虑bitset,不去重离散化后and一发就可以了.于是莫队求出每个区间的bitset.注意空间开不下,做多次即可.输出的东西错了都能调一年服了我了. #in ...

  7. BZOJ 4939 [Ynoi2016]掉进兔子洞(莫队+bitset)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4939 [题目大意] 给出一个数列,每个询问给出三个区间,问除去三个区间共有的数字外, ...

  8. YNOI2016:掉进兔子洞 (莫队+bitset)

    YNOI2016:掉进兔子洞 题意简述: 有 m 个询问,每次询问三个区间,把三个区间中同时出现的数一个一个删掉,问最后三个区间剩下的数的个数和,询问独立. 注意这里删掉指的是一个一个删,不是把等于这 ...

  9. p4688 [Ynoi2016]掉进兔子洞

    传送门 分析 我们考虑先将所有数离散化 之后我们对于每个状态用一个bitset来记录 其中第i段表示颜色i的信息 对于每一段信息均是段首若干1,剩余若干0表示这种颜色有多少个 于是我们不难想到莫队 答 ...

  10. luogu P4688 [Ynoi2016]掉进兔子洞

    luogu 我们要求的答案应该是三个区间长度\(-3*\)在三个区间中都出现过的数个数 先考虑数列中没有相同的数怎么做,那就是对三个区间求交,然后交集大小就是要求的那个个数.现在有相同的数,考虑给区间 ...

随机推荐

  1. fluent运行过程中转换边界

    我们以一个简单的VOF算例来说明,算例模型如下: 算例中空气为主相,水为次相.开始时刻,inlet_one设置为速度入口边界,速度为1m/s,且水的体积分数为100%,inlet_two设置为速度入口 ...

  2. /usr/bin/xauth: file /home/user/.Xauthority does not exist

    错误信息如下: /usr/bin/xauth: file /home/user/.Xauthority does not exist 错误原因:是因为添加用户时没有授权对应的目录,仅仅执行了usera ...

  3. 范仁义html+css课程---6、表格

    范仁义html+css课程---6.表格 一.总结 一句话总结: 表格中最常用的元素就是table.tr.td.th,还有语义化的thead.tbody.tfoot标签 1.表格构成三个基本要素? t ...

  4. python创建缩略图和选择轮廓效果

    # -*- encoding:utf-8 -*- ''' 改变颜色 --- 颜色反转''' from PIL import Image nest = Image.open("D:\\tk.j ...

  5. 从零开始搭建实验室Ubuntu服务器 | 深度学习工作站

    一个标准的数据分析码农必须要配一台超薄笔记本和一台高性能服务器,笔记本是日常使用,各种小问题的解决,同时也是用于远程连接终端服务器:高性能服务器就是核心的处理数据的平台,CPU.内存.硬盘容量.GPU ...

  6. free中buffer 与 cache 的区别

    通常人们所说的Cache就是指缓存SRAM. SRAM叫静态内存,“静态”指的是当我们将一笔数据写入SRAM后,除非重新写入新数据或关闭电源,否则写入的数据保持不变. 由于CPU的速度比内存和硬盘的速 ...

  7. Jenkins参数化构建--Git Parameter

    由于我们在测试过程中,可能需要在多个测试环境跑用例,这个时候就需要jenkins参数化了. Jenkins参数化一般常用的有两种方式:Choice和String Parameter两种 (1)Choi ...

  8. LODOP打印超文本有边距不居中的情况2

    之前的博文:LODOP打印项水平居中.之前的博文有介绍超文本和纯文本的居中方式,设置超文本打印项居中时,注意打印内容要在打印项本身宽度里居中.之前的博文超文本用的是个表格,而且表格本身没有margin ...

  9. 安卓手机与iOS手机的区别

    安卓手机与iOS手机的区别 1.操作系统不同  安卓手机都是安卓操作系统:IOS手机都是iOS操作系统. 目前安卓最新的系统是Android 8.1:iOS版本最新的是iOS 11. 2.操作方式不同 ...

  10. python is 和 == 区别(8)

    在python中is和==都说常用的运算符之一,主要用于检测两个变量是否相等,返回True或者False,具体区别在哪呢? 一.前言 在讲解is和==区别直接先讲解一下内置函数id(),其实在文章 p ...