Submission #1229548

#TimeUsernameProblemLanguageResultExecution timeMemory
1229548hashdfdfhSecret (JOI14_secret)C++20
100 / 100
341 ms4436 KiB
#include "secret.h"
#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 1e3 + 5;

// 保持原始数组
int arr[MAX_N];

// log2(MAXN)
const int LOG = 10;

int mask[MAX_N]; // 记录每个位置的区间信息
int dat[LOG][MAX_N]; // 存储预处理的最小值数据

// X X X X   X X X X          	3 * 2 = 6
// X X  X X  X X  X X			1 * 4 = 4
// X  X  X  X  X  X  X  X		0 * 8 = 0

// (n / 2 - 1) * 2		n - 2
// (n / 4 - 1) * 4		n - 4
// (n / 8 - 1) * 8     n - 8

// nlgn - (2 + 4 + 8 + ... + 2 ^ i)	2 ^ i <= n的最大值
// nlgn - (2 ^ (i + 1) - 2) = nlgn - 2 ^ (i + 1) + 2 
// nlgn - 2 * n + 2(不会超过8000)
// 8 * 3 - (2 + 4 + 8) = 10

void preprocess(int L, int R, int level) {
    // 区间只有1个元素,不用计算
    if (L == R) {
        return;
    }

    // 找到区间中间索引
    int mid = (L + R) / 2;

    // 预处理求dat(i到mid的最小值)
    // 从mid向左计算
    dat[level][mid] = arr[mid];
    for (int i = mid - 1; i >= L; i--) {
        dat[level][i] = Secret(arr[i], dat[level][i + 1]);
    }

    // 预处理求right(mid+1到r的最小值)
    // 从mid+1向右计算
    dat[level][mid + 1] = arr[mid + 1];
    for (int i = mid + 2; i <= R; i++) {
        dat[level][i] = Secret(dat[level][i - 1], arr[i]);
    }

    // 更新右半部分的mask标记
    for (int i = mid + 1; i <= R; i++) {
        mask[i] ^= (1 << level);
    }

    // 递归处理左右子区间
    preprocess(L, mid, level + 1);
    preprocess(mid + 1, R, level + 1);
}

// 末尾连续0的个数
int count_trailing_zeros(int x) {
    // 特殊处理0的情况
    if (x == 0) {
        return 32;
    }

    int count = 0;

    // 检查最低位是否为0
    while ((x & 1) == 0) {
        count++;
        // 右移一位
        x >>= 1;
    }
    return count;
}

void Init(int N, int A[]) {
    for (int i = 0; i < N; ++i) {
        arr[i] = A[i];
    }
    preprocess(0, N - 1, 0);
}

int Query(int L, int R) {
    // 只有一个元素
    if (L == R) {
        return arr[L];
    }

    // 计算mask的差异位数,确定查询层级
    // __builtin_ctz
    // diff_bits就是L和R,第一次被划分到两个区域的层级
    int diff_bits = count_trailing_zeros(mask[L] ^ mask[R]);
    return Secret(dat[diff_bits][L], dat[diff_bits][R]);
}
#Verdict Execution timeMemoryGrader output
Fetching results...