本文涉及知识点
分块
3655. 区间乘法查询后的异或 II
给你一个长度为 n 的整数数组 nums 和一个大小为 q 的二维整数数组 queries,其中 queries[i] = [li, ri, ki, vi]。
对于每个查询,需要按以下步骤依次执行操作:
设定 idx = li。
当 idx <= ri 时:
更新:nums[idx] = (nums[idx] * vi) % (10^9 + 7)。
将 idx += ki。
在处理完所有查询后,返回数组 nums 中所有元素的 按位异或 结果。
示例 1:
输入: nums = [1,1,1], queries = [[0,2,1,4]]
输出: 4
解释:
唯一的查询 [0, 2, 1, 4] 将下标 0 到下标 2 的每个元素乘以 4。
数组从 [1, 1, 1] 变为 [4, 4, 4]。
所有元素的异或为 4 ^ 4 ^ 4 = 4。
示例 2:
输入: nums = [2,3,1,5,4], queries = [[1,4,2,3],[0,2,1,2]]
输出: 31
解释:
第一个查询 [1, 4, 2, 3] 将下标 1 和 3 的元素乘以 3,数组变为 [2, 9, 1, 15, 4]。
第二个查询 [0, 2, 1, 2] 将下标 0、1 和 2 的元素乘以 2,数组变为 [4, 18, 2, 15, 4]。
所有元素的异或为 4 ^ 18 ^ 2 ^ 15 ^ 4 = 31。
提示:
1 < = n = = n u m s . l e n g t h < = 1 0 5 1 <= n == nums.length <= 10^5 1<=n==nums.length<=105
1 < = n u m s [ i ] < = 1 0 9 1 <= nums[i] <= 10^9 1<=nums[i]<=109
1 < = q = = q u e r i e s . l e n g t h < = 1 0 5 1 <= q == queries.length <= 10^5 1<=q==queries.length<=105
queries[i] = [li, ri, ki, vi]
0 <= li <= ri < n
1 <= ki <= n
1 < = v i < = 1 0 5 1 <= vi <= 10^5 1<=vi<=105
分块 差分数组
如果 k i ≥ s q r t ( N ) ki \ge sqrt(N) ki≥sqrt(N),直接相乘。
diff[k][i]的值是x表示将 nums[i],nums[i+k],nums[i+2k] ⋯ \cdots ⋯ 都乘以x。
len = ( r i − l i ) ÷ k i + 1 (r_i - l_i) \div k_i+1 (ri−li)÷ki+1
rr = l i + k i × l e n l_i + k_i \times len li+ki×len
对查询i,可以:
d i f f [ k i ] [ l i ] × v i , d i f f [ k i ] [ r r ] ÷ v i diff[k_i][l_i] \times v_i,diff[k_i][rr] \div v_i diff[ki][li]×vi,diff[ki][rr]÷vi
代码
核心代码
cpp
template<long long MOD = 1000000007,class T1 = int, class T2 = long long>
class C1097Int
{
public:
C1097Int(T1 iData = 0) :m_iData(iData% MOD)
{
}
C1097Int(T2 llData) :m_iData(llData% MOD) {
}
C1097Int operator+(const C1097Int& o)const
{
return C1097Int(((T2)m_iData + o.m_iData) % MOD);
}
C1097Int& operator+=(const C1097Int& o)
{
m_iData = ((T2)m_iData + o.m_iData) % MOD;
return *this;
}
C1097Int& operator-=(const C1097Int& o)
{
m_iData = ((T2)MOD + m_iData - o.m_iData) % MOD;
return *this;
}
C1097Int operator-(const C1097Int& o)const
{
return C1097Int(((T2)MOD + m_iData - o.m_iData) % MOD);
}
C1097Int operator*(const C1097Int& o)const
{
return((T2)m_iData * o.m_iData) % MOD;
}
C1097Int& operator*=(const C1097Int& o)
{
m_iData = ((T2)m_iData * o.m_iData) % MOD;
return *this;
}
C1097Int operator/(const C1097Int& o)const
{
return *this * o.PowNegative1();
}
C1097Int& operator/=(const C1097Int& o)
{
*this *= o.PowNegative1();
return *this;
}
bool operator==(const C1097Int& o)const
{
return m_iData == o.m_iData;
}
bool operator<(const C1097Int& o)const
{
return m_iData < o.m_iData;
}
C1097Int pow(T2 n)const
{
C1097Int iRet = (T1)1, iCur = *this;
while (n)
{
if (n & 1)
{
iRet *= iCur;
}
iCur *= iCur;
n >>= 1;
}
return iRet;
}
C1097Int PowNegative1()const
{
return pow(MOD - 2);
}
T1 ToInt()const
{
return ((T2)m_iData + MOD) % MOD;
}
private:
T1 m_iData = 0;;
};
class Solution {
public:
int xorAfterQueries(vector<int>& nums, vector<vector<int>>& queries) {
typedef C1097Int<> BI;
const int N = nums.size();
vector<BI> bn(nums.begin(),nums.end()); ;
const int K = sqrt(N);
vector<vector<BI>> diff(K, vector<BI>(N,1));
for (auto& v : queries) {
if (v[2] >= K) {
for (int i = v[0]; i <= v[1]; i += v[2]) {
bn[i] *= v[3];
}
}
else {
const int len = (v[1] - v[0]) / v[2] + 1;
const int rr = v[0] + v[2] * len;
diff[v[2]][v[0]] *= v[3];
if (rr < N) {
diff[v[2]][rr] /= v[3];
}
}
}
for (int k = 0; k < K; k++) {
for (int k1 = 0; k1 < k; k1++) {
BI tmp = 1;
for (int k2 = k1; k2 < N; k2 += k) {
tmp *= diff[k][k2];
bn[k2] *= tmp;
}
}
}
int ans = 0;
for (auto& bi : bn) {
ans ^= bi.ToInt();
}
return ans;
}
};
单元测试
cpp
vector<int> nums;
vector<vector<int>> queries;
TEST_METHOD(TestMethod11)
{
nums = { 1,1,1 }, queries = { {0,2,1,4} };
auto res = Solution().xorAfterQueries(nums, queries);
AssertEx(4, res);
}
TEST_METHOD(TestMethod12)
{
nums = { 2,3,1,5,4 }, queries = { {1,4,2,3},{0,2,1,2} };
auto res = Solution().xorAfterQueries(nums, queries);
AssertEx(31, res);
}

扩展阅读
| 我想对大家说的话 |
|---|
| 工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
| 学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
| 有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
| 员工说:技术至上,老板不信;投资人的代表说:技术至上,老板会信。 |
| 闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
| 如果程序是一条龙,那算法就是他的是睛 |
| 失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法 用**C++**实现。
