【卡常 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」棋盘游戏[二分图博弈、匈牙利算法]
题意 题目链接 分析 二分图博弈经典模型,首先将棋盘二分图染色. 考虑在某个最大匹配中: 如果存在完美匹配则先手必败,因为先手选定的任何一个起点都在完美匹配中,而后手则只需要走这个点的匹配点,然后先手 ...
随机推荐
- SpringBoot配置属性二
server配置 server.address指定server绑定的地址 server.compression.enabled是否开启压缩,默认为false. server.compression.e ...
- tinkphp5使用中碰到的问题 持续更新
1.使用助手函数(如controller(),model(),validate())进行实例化时只需要引入think\Controller或think\Model或think\Validate即可,无 ...
- iOS文字转语音(语音朗读)
1.第一步导入framework 2.导入头文件 #import <AVFoundation/AVSpeechSynthesis.h> 3. 设置代理 并写下面方法 (注:代理方法用不到 ...
- atcoder square869120Contest#3 F 寿司
省选round1的时候dalao的推荐——atcoder的题目码量不大,但很巧妙,题目比较难找,挂个链冷静一下:http://s8pc-3.contest.atcoder.jp/tasks/s8pc_ ...
- 实例/静态工厂方法得到bean
<bean id="a" class="com.yundaex.wms.config.TestBeanChild" /> <bean id=& ...
- C#字符串变量使用
string由于是引用类型,所以,声明的字符串变量会存储到堆上,而且该变量是不可变的,一旦初始化了该变量,该内存区域中存储的内容将不能更改.在对字符串操作时,是在堆上创建了一个新的字符串变量,并将新的 ...
- Mybatis基础配置及增删查改操作
一.简介 平时我们都用JDBC访问数据库,除了需要自己写SQL之外,还必须操作Connection, Statement, ResultSet 这些其实只是手段的辅助类. 不仅如此,访问不同的表,还会 ...
- linux debian 时间设置中无法选择“自动设定时间和日期”
没有安装ntpdate 执行:apt-get install ntpdate ntp.sjtu.edu.cn 202.120.2.101 (上海交通大学网络中心NTP服务器地址)s1a.time.ed ...
- placeholder的兼容处理方法
placeholder是html5新增的一个属性,极大的减轻了表单提示功能的实现,但是对于IE6-IE9真的是只能靠自己写啦! 但是在自己写时会掉进了一个坑里,还好用了一会时间还是爬出来啦. 最终的解 ...
- Class 学习 (Es6阮一峰)
es5 构造函数 实例: function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () ...