我也很想过,要写些《闲话》类的东西,然而考虑到其中所必定会带有的负能量,以及预想到校长和卷爷——或许还有狗狗——在评论区的辛辣的嘲讽,终究作罢。
说到底我并没有写《闲话》的资格。卷爷成绩好,所以他做什么都是合情合理的。我不是那样的。我什么权利也没有。我什么也不是。
我的心底只有寒冷、黑暗和死亡。我的生活只值得咒骂而不值得闲谈。我只能把它命名为《咒骂》而再没有别的内容。
可此后这念头就深深扎根在心底。像一座死火山,哪怕它是 “死” 的,它的内部也仍然是滚烫的岩浆。因此我借博客前的一点空间,稍微写点什么吧。
最近发生了很多不可思议的事,而且接二连三:先是角膜塑形镜意外遗失,接着牙套遗失,然后框架眼镜的眼镜腿断掉,现在考试连续垫底。
这似乎是某种预兆。某种我不愿去承认,但已经心知肚明的预兆。
但,或许,这也是好事。它至少让我的心理负担没那么重。
我已经对自己的弱小熟视无睹了。对自己的无能见怪不怪了。对自己的愚蠢毫不意外了。
题目背景
因为
O
U
Y
E
\sf OUYE
OUYE 过分内卷,像我一样的普通人已经 没有 生存 空间 了。
题目描述
考虑
2
k
2^k
2k 个叶子的线段树,每个节点的值是子节点的较大值。
叶子值是 [ 1 , 2 k ] [1,2^k] [1,2k] 给定排列。现在 q q q 次询问 x , y x,y x,y,问 x x x 值最多能在多少个节点上出现,如果交换至多 y y y 次叶子的值。
强制在线,且空间限制 16 M i B 16\rm MiB 16MiB 。
数据范围与提示
k
⩽
19
k\leqslant 19
k⩽19 而
q
⩽
2
×
1
0
5
q\leqslant 2\times 10^5
q⩽2×105 。
若 y ≠ 0 y\ne 0 y=0,则只需判断某层上,是否有节点拥有至多 y y y 个大于 x x x 的值。
y = 0 y=0 y=0 时线段树没有变动,可以直接数出答案。故下略。
看到大于 x x x,考虑从大到小依次处理 x x x 。
每次将一个新元素插入,这将影响到 k k k 层内各一个节点。然后我们要维护每层的 min c n t \min cnt mincnt 。用数据结构维护,似乎是 O ( k 2 2 k ) \mathcal O(k^22^k) O(k22k) 的复杂度。
其实每层记录 min \min min 的出现次数,发现 min \min min 变化后暴力重新计算即可。因为有 L L L 个节点的层中, min \min min 不会超过 2 k L 2^k\over L L2k,而每次增加需要 O ( L ) \mathcal O(L) O(L) 重新计算,因此 k k k 层的总复杂度 O ( k 2 k ) \mathcal O(k2^k) O(k2k) 。
这样我们就得到每个 x x x 想要在 t t t 个节点上出现时, y y y 至少是多少。如果存储下来,就可以在线处理所有询问了。复杂度 O ( k 2 k + q log k ) \mathcal O(k2^k+q\log k) O(k2k+qlogk) 。若在线,空间复杂度 O ( k 2 k ) \mathcal O(k2^k) O(k2k),若离线,空间复杂度 O ( 2 k + q ) \mathcal O(2^k+q) O(2k+q) 。
扫描线
是每个
x
x
x 去查询可用的线段树节点。
反过来考虑:每个线段树节点能给 x x x 提供什么。
显然第 t t t 大的值 v v v 给出了限制:若 x ⩾ v x\geqslant v x⩾v,则 y ⩾ t − 1 y\geqslant t{-}1 y⩾t−1 时能获得该区间的答案。
注意到每层只有 O ( 2 k ) \mathcal O(2^k) O(2k) 个这样的贡献,直接用数组暴力扫描线记下答案即可。
求出的这个数组和 扫描线
中得到的结果是相同的。
注意到 半平面
中,给出的限制
y
⩾
t
−
1
y\geqslant t{-}1
y⩾t−1 只有
L
L
L 种,其中
L
L
L 是单个节点的长度。
因此我们记录 f ( t ) f(t) f(t) 为,在 y ⩾ t − 1 y\geqslant t{-}1 y⩾t−1 时, x ⩾ f ( t ) x\geqslant f(t) x⩾f(t) 可达到该层。
由于每层的 f f f 的长度和是 O ( 2 k ) \mathcal O(2^k) O(2k),空间复杂度就是 O ( 2 k ) \mathcal O(2^k) O(2k) 的。
询问仍然可以二分,时间复杂度 O ( k 2 k + q log k ) \mathcal O(k2^k+q\log k) O(k2k+qlogk),空间复杂度 O ( 2 k ) \mathcal O(2^k) O(2k) 。
怎么强制在线?利用上一个答案。
然而答案只有 k k k 种,因此将这 O ( q k ) \mathcal O(qk) O(qk) 个询问离线下来,我们也得到可通过的做法。
#include
#include // Almighty XJX yyds!!
#include // oracle: ZXY yydBUS!!!
#include // rainybunny root of the evil.
#include
using llong = long long;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
# define rep0(i,a,b) for(int i=(a); i!=(b); ++i)
inline int readint(){
int a = 0, c = getchar(), f = 1;
for(; !isdigit(c); c=getchar()) if(c == '-') f = -f;
for(; isdigit(c); c=getchar()) a = a*10+(c^48);
return a*f;
}
const int MAXK = 19;
int a[1<<MAXK]; int* tag[MAXK];
int ori[1<<MAXK]; /** for y = 0 */
const int INF = 0x3fffFFFF;
int tmp[1<<MAXK];
int main(){
int n = readint(), k = readint(), typ = readint();
rep0(i,0,n) a[i] = readint()-1;
rep0(j,0,k){ // merge for each layer
tag[j] = new int[2<<j];
std::fill_n(tag[j],2<<j,INF);
int* l = a; int* r = a+(2<<j);
for(; l!=a+n; r+=(2<<j)){
int* const mid = l+(1<<j);
ori[std::min(*l,*mid)] = j; // lose here
std::merge(l,mid,mid,r,tmp,std::greater<int>());
memcpy(l,tmp,(2<<j)<<2); // copy back
for(int* i=tag[j]; l!=r; ++l,++i)
*i = std::min(*i,*l); // corresponding
}
}
ori[n-1] = k; // the final winner
for(int q=readint(),x,y,ans=0; q; --q){
x = readint(), y = readint();
if(typ) x ^= ans, y ^= ans;
if(!y){ printf("%d\n",ans=ori[x-1]); continue; }
int l = 31-__builtin_clz(y); /** smaller than @a y */
int r = 31-__builtin_clz(x--); /** too big to replace */
if(l > r){ printf("%d\n",ans=r); continue; }
while(l != r){
const int mid = (l+r+1)>>1;
if(tag[mid-1][y] <= x) // acceptable
l = mid; else r = mid-1;
}
printf("%d\n",ans=r);
}
return 0;
}