好不容易算着块大小,裸的分块才能过随机极限数据;然而这题在线的数据都竟然是构造的……

题目描述

有 $n$ 个数字,第 $i$ 个数字为 $a_i$。

有 $m$ 次询问,每次给出 $k_i$ 个区间,每个区间表示第 $l_{i, j}$ 到 $r_{i, j}$ 的数字,求这些区间中一共出现了多少种不同的数字。

部分数据强制在线。

第一行包含三个整数 $n, m, p$,$p$ 为 $0$ 或 $1$ 表示是否强制在线。

第二行 $n$ 个正整数,第 $i$ 个表示 $a_i$。

接下来依次给出每个询问,每个询问第一行一个正整数,表示 $k_i$,接下来 $k_i$ 行,每行两个正整数,分别表示 $l_{i, j}$ 和 $r_{i, j}$,若 $p = 1$ 且这不是第一个询问,输入的 $l_{i, j}$ 和 $r_{i, j}$ 是经过加密的,你需要将这两个数字分别异或上上一个询问的答案,对 $n$ 取模后再加 $1$,两者较小值为真实的 $l_{i, j}$,较大值为真实的 $r_{i, j}$。

对于全部数据,$1 \leq n, m, \sum k_i, a_i \leq 10^5, 1 \leq l_{i, j} \leq r_{i, j} \leq n$。

  • 子任务 $\rm 1(points:10)$:$n, m, \sum k_i, a_i \leq 5000$
  • 子任务 $\rm 2(points:10)$:$n, m, \leq 5000$
  • 子任务 $\rm 3(points:20)$:$k_i = 1$
  • 子任务 $\rm 4(points:20)$: $p = 0$
  • 子任务 $\rm 5(points:20)$:$1 \leq n, m, \sum k_i, a_i \leq 50000$
  • 子任务 $\rm 6(points:20)$:无特殊限制

题目分析

首先会有一个朴素的分块想法:将序列分块,每个块维护一个bitset。

但是我们会很快意识到bitset一次或操作的复杂度是$O(值域)$的,这么大的复杂度显然我们无法接受。这个想法的最大瓶颈在于中间连续一段bitset的操作复杂度太高。

用以维护分块处理这个瓶颈的方法有两种:线段树/ST表,也就是用基础的区间数据结构来维护一段区间的bitset值。

让我们冷静分析一下这两种方法的复杂度:

我们很容易想到用`bitset`做,先不管空间限制的话会想到这两种方法:

  • 1. 线段树:构造 $O({ n^2\over\omega })​$ ,询问 $O({ n^2\over\omega }log_2n)​$ 。
  • 2. ST表:构造 $O({ n^2\over\omega }log_2n)$ ,询问 $O({ n^2\over\omega })$ 。

都是无法承受的,于是考虑分块来降低复杂度,只记录块之间的信息:

  • 1. 线段树:构造 $O({ n^2\over\omega S })$ ,询问 $O({ n^2\over\omega }log_2{ n\over S }+nS)$ 。
  • 2. ST表:构造 $O({ n^2\over\omega S }log_2{ n\over S })$ ,询问 $O({ n^2\over\omega }+nS)$ 。

发现线段树的那个 $log_2{n\over S}$ 搞不掉,于是gg了,而ST表 $S$ 设置的正常点复杂度都没什么问题。

不过这道题卡内存,所以 $S$ 需要给大点。

这是一个非常规分块的技巧,好像叫四毛子算法?

——摘自ZZK的题解

那么,只需要手写bitset+卡常+分块就可以解决这题了。

 #include<bits/stdc++.h>
const int maxn = ;
const int maxp = (>>)+;
const int maxt = (<<)-;
const int maxb = ; int a[maxn],dt[maxn],lg2[maxn],t[maxn],tot;
struct bitset
{
unsigned int a[maxp];
bitset operator |(bitset b) const
{
bitset c;
for (int i=; i<=tot; i++)
c.a[i] = a[i]|b.a[i];
return c;
}
void reset()
{
for (int i=; i<=tot; i++) a[i] = ;
}
void set(int x)
{
a[x>>] |= 1u<<(x&);
}
int count()
{
int ret = ;
for (int i=; i<=tot; i++)
ret += dt[a[i]>>]+dt[a[i]&maxt];
return ret;
}
}f[maxb][],ans;
int n,m,p,lastans;
int blk[maxn],size,bkTot; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void init()
{
for (int i=, Mx=; i<=Mx; i++)
for (int x=i; x; x&=(x-)) ++dt[i];
for (int i=, Mx=; i<=Mx; i++)
lg2[i] = lg2[i>>]+;
}
void deal(int l, int r)
{
int ls = blk[l], rs = blk[r];
if (ls==rs){
for (int i=l; i<=r; i++) ans.set(a[i]);
return;
}
for (int i=l; blk[i]==ls; i++) ans.set(a[i]);
for (int i=r; blk[i]==rs; i--) ans.set(a[i]);
if (ls+ < rs){
int t = lg2[rs-ls-];
ans = ans|f[ls+][t]|f[rs-(<<t)][t];
}
}
int main()
{
n = read(), m = read(), p = read();
init(), size = sqrt(1.2*n*log2(n+)), bkTot = n/size+;
for (int i=; i<=n; i++)
t[i] = a[i] = read(), blk[i] = i/size+;
std::sort(t+, t+n+);
tot = std::unique(t+, t+n+)-t-;
for (int i=; i<=n; i++)
a[i] = std::lower_bound(t+, t+tot+, a[i])-t,
f[blk[i]][].set(a[i]);
tot >>= ;
for (int j=; j<=lg2[bkTot]; j++)
for (int i=; i+(<<j)-<=bkTot; i++)
f[i][j] = f[i][j-]|f[i+(<<(j-))][j-];
for (int tim=; m; --m, ++tim)
{
ans.reset();
for (int k=read(); k; --k)
{
int l = read(), r = read();
if (p&&tim) l = (l^lastans)%n+, r = (r^lastans)%n+;
if (l > r) std::swap(l, r);
deal(l, r);
}
lastans = ans.count();
printf("%d\n",lastans);
}
return ;
}

END

【卡常 bitset 分块】loj#6499. 「雅礼集训 2018 Day2」颜色的更多相关文章

  1. #6499. 「雅礼集训 2018 Day2」颜色 [分块,倍增,bitset]

    bitset压位,因为是颜色数,直接倍增,重合部分不管,没了. // powered by c++11 // by Isaunoya #include <bits/stdc++.h> #d ...

  2. Loj #6503. 「雅礼集训 2018 Day4」Magic

    Loj #6503. 「雅礼集训 2018 Day4」Magic 题目描述 前进!前进!不择手段地前进!--托马斯 · 维德 魔法纪元元年. 1453 年 5 月 3 日 16 时,高维碎片接触地球. ...

  3. 「雅礼集训 2018 Day2」农民

    传送门 Description  「搞 OI 不如种田.」 小 D 在家种了一棵二叉树,第 ii 个结点的权值为 \(a_i\). 小 D 为自己种的树买了肥料,每天给树施肥. 可是几天后,小 D 却 ...

  4. 「LOJ #6500」「雅礼集训 2018 Day2」操作

    description LOJ 6500 solution 根据常有套路,容易想到将区间差分转化为异或数组上的单点修改,即令\(b_i=a_i \ xor\ a_{i-1}\), 那么将\([l,l+ ...

  5. LOJ #6509. 「雅礼集训 2018 Day7」C

    神仙题 LOJ #6509 题意 给定一棵树,点权为0/1,每次随机一个点(可能和之前所在点相同)走到该点并将其点权异或上1 求期望的移动距离使得所有点点权相同 题解 根本不会解方程 容易发现如果一个 ...

  6. LOJ#6503.「雅礼集训 2018 Day4」Magic[容斥+NTT+启发式合并]

    题意 \(n\) 张卡牌 \(m\) 种颜色,询问有多少种本质不同的序列满足相邻颜色相同的位置数量等于 \(k\). 分析 首先本质不同不好直接处理,可以将同种颜色的卡牌看作是不相同的,求出答案后除以 ...

  7. loj#6033. 「雅礼集训 2017 Day2」棋盘游戏(二分图博弈)

    题意 链接 Sol 第一次做在二分图上博弈的题..感觉思路真是清奇.. 首先将图黑白染色. 对于某个点,若它一定在最大匹配上,那么Bob必胜.因为Bob可以一直沿着匹配边都,Alice只能走非匹配边. ...

  8. loj#6032. 「雅礼集训 2017 Day2」水箱(并查集 贪心 扫描线)

    题意 链接 Sol 神仙题+神仙做法%%%%%%%% 我再来复述一遍.. 首先按照\(y\)坐标排序,然后维护一个扫描线从低处往高处考虑. 一个连通块的内状态使用两个变量即可维护\(ans\)表示联通 ...

  9. [LOJ#6033]. 「雅礼集训 2017 Day2」棋盘游戏[二分图博弈、匈牙利算法]

    题意 题目链接 分析 二分图博弈经典模型,首先将棋盘二分图染色. 考虑在某个最大匹配中: 如果存在完美匹配则先手必败,因为先手选定的任何一个起点都在完美匹配中,而后手则只需要走这个点的匹配点,然后先手 ...

随机推荐

  1. angularJs 自定义指令传值---父级与子级之间的通信

    angularJs自定义指令用法我忽略,之前有写过,这里只说一下父子级之间如何传值: 例如: 模块我定义为myApp,index.html定义 <my-html bol-val="bo ...

  2. linux 初始配置(centos)-网络和可视化界面

    1. 执行命令查看ip:ip addr 2. 如果没有或取到,要查看网卡是否启动,及ip配置是否正确,请先将ONBOOT改成yes,表示开机即启动 [lobin@localhost ~]$ cat / ...

  3. JS高级学习历程-17

    [正则案例] 1 匹配手机号码

  4. virtualenv模块安装

    依赖包管理模块(virtualenv) virtualenv是Python的虚拟环境,可以在同一台PC隔离不同的python开发环境.virtualenv可以创建一个隔离的python环境(沙盒).使 ...

  5. discuz 3.x ssrf分析

    discuz 3.x版本ssrf漏洞分析 漏洞促发点\souce\module\forum\forum_ajax.php 最后看到了这里 ***$_GET['action']='downremotei ...

  6. Selenium 开源书(一): Selenium历史

    Selenium历史 Selenium最初由Jason Huggins于2004年开发,作为ThoughtWorks的内部工具.Huggins后来加入了ThoughtWorks的其他程序员和测试人员, ...

  7. python 1 学习廖雪峰博客

    输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'hello, world',用代码实现如下: >>> print('hello, world') p ...

  8. node.js安装Oracledb指导文档

    https://community.oracle.com/docs/DOC-931127

  9. Corn 表达式

    CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表.CronTr ...

  10. 原创 html动态表格

    <table id="opttb"> <asp:Repeater ID="tempOptions" runat="server&qu ...