【卡常 bitset 分块】loj#6499. 「雅礼集训 2018 Day2」颜色
好不容易算着块大小,裸的分块才能过随机极限数据;然而这题在线的数据都竟然是构造的……
题目描述
有 $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」颜色的更多相关文章
- #6499. 「雅礼集训 2018 Day2」颜色 [分块,倍增,bitset]
bitset压位,因为是颜色数,直接倍增,重合部分不管,没了. // powered by c++11 // by Isaunoya #include <bits/stdc++.h> #d ...
- Loj #6503. 「雅礼集训 2018 Day4」Magic
Loj #6503. 「雅礼集训 2018 Day4」Magic 题目描述 前进!前进!不择手段地前进!--托马斯 · 维德 魔法纪元元年. 1453 年 5 月 3 日 16 时,高维碎片接触地球. ...
- 「雅礼集训 2018 Day2」农民
传送门 Description 「搞 OI 不如种田.」 小 D 在家种了一棵二叉树,第 ii 个结点的权值为 \(a_i\). 小 D 为自己种的树买了肥料,每天给树施肥. 可是几天后,小 D 却 ...
- 「LOJ #6500」「雅礼集训 2018 Day2」操作
description LOJ 6500 solution 根据常有套路,容易想到将区间差分转化为异或数组上的单点修改,即令\(b_i=a_i \ xor\ a_{i-1}\), 那么将\([l,l+ ...
- LOJ #6509. 「雅礼集训 2018 Day7」C
神仙题 LOJ #6509 题意 给定一棵树,点权为0/1,每次随机一个点(可能和之前所在点相同)走到该点并将其点权异或上1 求期望的移动距离使得所有点点权相同 题解 根本不会解方程 容易发现如果一个 ...
- LOJ#6503.「雅礼集训 2018 Day4」Magic[容斥+NTT+启发式合并]
题意 \(n\) 张卡牌 \(m\) 种颜色,询问有多少种本质不同的序列满足相邻颜色相同的位置数量等于 \(k\). 分析 首先本质不同不好直接处理,可以将同种颜色的卡牌看作是不相同的,求出答案后除以 ...
- loj#6033. 「雅礼集训 2017 Day2」棋盘游戏(二分图博弈)
题意 链接 Sol 第一次做在二分图上博弈的题..感觉思路真是清奇.. 首先将图黑白染色. 对于某个点,若它一定在最大匹配上,那么Bob必胜.因为Bob可以一直沿着匹配边都,Alice只能走非匹配边. ...
- loj#6032. 「雅礼集训 2017 Day2」水箱(并查集 贪心 扫描线)
题意 链接 Sol 神仙题+神仙做法%%%%%%%% 我再来复述一遍.. 首先按照\(y\)坐标排序,然后维护一个扫描线从低处往高处考虑. 一个连通块的内状态使用两个变量即可维护\(ans\)表示联通 ...
- [LOJ#6033]. 「雅礼集训 2017 Day2」棋盘游戏[二分图博弈、匈牙利算法]
题意 题目链接 分析 二分图博弈经典模型,首先将棋盘二分图染色. 考虑在某个最大匹配中: 如果存在完美匹配则先手必败,因为先手选定的任何一个起点都在完美匹配中,而后手则只需要走这个点的匹配点,然后先手 ...
随机推荐
- video,audio用法小例子
用此小程序设计播放/暂停,放大缩小 <!DOCTYPE html> <html> <body> <div style="text-align:cen ...
- jsp网站访问次数统计
JSP 点击量统计 有时候我们需要知道某个页面被访问的次数,这时我们就需要在页面上添加页面统计器,页面访问的统计一般在用户第一次载入时累加该页面的访问数上. 要实现一个计数器,您可以利用应用程序隐式对 ...
- QCTF 2018线上赛 writeup
本次算是被QCTF打趴了,本来做题时间就少(公司无限开会,开了一天,伪借口),加上难度和脑洞的增大,导致这次QCTF又酱油了...就连最基本的签到题都没做出来...这就很气 好了,以下是解题思路 MI ...
- Educational Codeforces Round 65 (Rated for Div. 2) B. Lost Numbers
链接:https://codeforces.com/contest/1167/problem/B 题意: This is an interactive problem. Remember to flu ...
- sql语句优化及后一条减前一条
sql语句优化: 1.表加索引 2.少用like,直接用=所有值 3.where语句把能大量筛查的条件写在前面 4.数据量大时,参与计算的值相同时只取一条 后一条减前一条, select houec, ...
- C# 操作 sqlite
1.下载sqlite:http://system.data.sqlite.org/downloads/1.0.94.0/sqlite-netFx20-setup-bundle-x86-2005-1.0 ...
- Java基础:(三)运算
一.参数传递 Java的参数是以值传递的形式传入方法中,而不是引用传递. 二.隐式类型转换 Java不能隐式执行向下转型,因为这会使精度降低:但是使用 += 运算符可以执行隐式类型转换. float ...
- JS根据选择的日期计算年龄
本例中用的是easyUI的datebox $('#cal_birthday').datebox({ onSelect: function(date){ //根据选则的日期计算年龄 //alert(da ...
- socket tcp使用recv接收数据时,返回errno错误代码88
原因:就是recv函数的第一个参数不是可用的,也就是第一个参数不是建立连接时返回的文件描述符. 解决方法:xxx
- Python+selenium之跳过测试和预期失败
在运行测试时,需要直接跳过某些测试用例,或者当用例符合某个条件时跳过测试,又或者直接将测试用例设置为失败.unittest单元测试框架提供了实现这些需求的装饰器. 1.unittest.skip(re ...