总览:
做了一道毒瘤题 带插区间k小
并且树套树常数过大,过不去 (毒瘤出题人毒瘤卡常)
于是就学习了新科技:值域分块
实质是分块套分块,先给序列分块,再在每个块中给值域分块
(分块用链表实现好方便
具体题目具体分析
T1 P4278 带插入区间K小值
思路:
bzoj一个点平均15s,luogu一个点1s……
先对序列分块,方便取出 [ l , r ] [l,r] [l,r]
再对值域分块,方便查询 k k k 小
要 O ( 1 ) O(1) O(1) 查询 [ l , r ] [l,r] [l,r] 中值在 [ v a l l , v a l r ] [val_l,val_r] [vall,valr] 中的数的个数
于是可以对值域做序列上的前缀和
查询时先 O ( n ) O(\sqrt n) O(n) 将块取出,再 O ( n ) O(\sqrt n) O(n) 找到 k k k 小
修改,插入时要更新每个序列块中一个值域块前缀和, O ( n ) O(\sqrt n) O(n)
如果在一个块中插入过多,将这个块分裂成两个块即可
块状链表实现
找个人少的时候卡过去
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC op