Maximum And Queries (hard version)

发布时间 2023-12-29 18:14:07作者: Tx_Lcy

题目传送门

感觉这题比 \(\rm F\) 难啊,\(\rm F\) 就是个板子,但为啥这题是蓝的,\(\rm F\) 是紫的。

思路

首先考虑 \(nq\) 怎么做。

发现很简单,按位贪心就行了。

具体地说,从大到小枚举二进制位,判断答案中能否出现这一位,若 \(i\) 当前这一位没有值,那么必须被补全到这个值,否则无所谓,然后拿当前代价和剩余能操作的次数比较即可。

然后考虑优化计算代价的过程。

先给出暴力计算代价的代码:

for (int s=20;~s;--s){
    int g=1ll<<(s+1),re=0,gx=mx|(1ll<<s);
    for (int i=1;i<=n;++i){
        int t=a[i]%g;
        if ((a[i]&mx)!=mx) re+=1ll<<s;
        if ((a[i]&mx)==mx && (a[i]&gx)!=gx) re+=(1ll<<s)-t;
    }
    if (k>=re) k-=re,mx|=1ll<<s;
}

首先这个

if ((a[i]&mx)!=mx) re+=1ll<<s;

是很好优化的,高维前缀和即可。

考虑下面那个 \(\verb!if!\) 如何优化。

我们继续把它拆成

if ((a[i]&mx)==mx && (a[i]&gx)!=gx) re+=1ll<<s;
if ((a[i]&mx)==mx && (a[i]&gx)!=gx) re-=t;

上面那个柿子同样很好优化,仅需计算出是 \(\verb!mx!\) 的超集且不是 \(\verb!gx!\) 的超集的个数即可,同样可以高维前缀和。

至于下面那个柿子,我们考虑预处理一个数组 \(g_{p,s}\) 表示 \(s\) 所有超集的权值 \(\bmod\ 2^{p+1}\) 后的和,然后同样的道理,可以 \(\mathcal O(1)\) 算出结果。

这样这题就做完了,复杂度两只 \(\log\)

代码

提交记录