AT_tkppc3_d 巨大チェスボード 题解

AT_tkppc3_d 巨大チェスボード 题解

题意简述

给定 H 行 W 列的不规则棋盘:

  • 格子 (i,j)(i,j)(i,j) 颜色为国际象棋样式,(1,1)(1,1)(1,1) 为黑色,相邻格子颜色不同。
  • 第 i 行高度为 a[i]a[i]a[i],第 j 列宽度为 b[j]b[j]b[j],格子 (i,j)(i,j)(i,j) 面积 = a[i]×b[j]a[i] \times b[j]a[i]×b[j]。
  • Q 次询问矩形 (px,py)(px,py)(px,py) 到 (qx,qy)(qx,qy)(qx,qy),求:黑格总面积 − 白格总面积。

数据范围:H,W,Q≤105H,W,Q \leq 10^5H,W,Q≤105,a[i],b[i]≤104a[i],b[i] \leq 10^4a[i],b[i]≤104,要求 O(H+W+Q)O(H+W+Q)O(H+W+Q) 算法。

核心思路

1. 贡献符号化

黑格贡献 +a[i]b[j]+a[i]b[j]+a[i]b[j],白格贡献 −a[i]b[j]-a[i]b[j]−a[i]b[j],可统一表示为:
val(i,j)=(−1)i+j⋅a[i]⋅b[j]val(i,j) = (-1)^{i+j} \cdot a[i] \cdot b[j]val(i,j)=(−1)i+j⋅a[i]⋅b[j]

2. 二维和拆分为一维乘积

∑i=pxqx∑j=pyqy(−1)i+ja[i]b[j]=(∑i=pxqx(−1)ia[i])⋅(∑j=pyqy(−1)jb[j])\sum_{i=px}^{qx}\sum_{j=py}^{qy} (-1)^{i+j}a[i]b[j] = \left(\sum_{i=px}^{qx} (-1)^i a[i]\right) \cdot \left(\sum_{j=py}^{qy} (-1)^j b[j]\right)∑i=pxqx∑j=pyqy(−1)i+ja[i]b[j]=(∑i=pxqx(−1)ia[i])⋅(∑j=pyqy(−1)jb[j])

3. 前缀和预处理

定义交替前缀和:

  • sa\[i\] = 前 i 行的交替和:奇数行 +a[i]+a[i]+a[i],偶数行 −a[i]-a[i]−a[i]
  • sb\[i\] = 前 i 列的交替和:奇数列 +b[i]+b[i]+b[i],偶数列 −b[i]-b[i]−b[i]

区间 [L,R][L,R][L,R] 和:
sumA=sa[R]−sa[L−1]sumA = sa[R] - sa[L-1]sumA=sa[R]−sa[L−1]
sumB=sb[R]−sb[L−1]sumB = sb[R] - sb[L-1]sumB=sb[R]−sb[L−1]

最终答案 = sumA×sumBsumA \times sumBsumA×sumB

算法流程

  1. 读入 H,W,QH, W, QH,W,Q
  2. 预处理 aaa 数组,计算 sasasa 前缀和
  3. 预处理 bbb 数组,计算 sbsbsb 前缀和
  4. 对每个询问:
    • 计算行区间 [px,qx][px,qx][px,qx] 的 sumAsumAsumA
    • 计算列区间 [py,qy][py,qy][py,qy] 的 sumBsumBsumB
    • 输出 sumA×sumBsumA \times sumBsumA×sumB

复杂度分析

  • 预处理:O(H+W)O(H + W)O(H+W)
  • 单次查询:O(1)O(1)O(1)
  • 总复杂度:O(H+W+Q)O(H + W + Q)O(H+W+Q),可通过 10510^5105 规模数据

样例1解释

输入中:
a=[7,35,5]a = [7,35,5]a=[7,35,5],计算得:
sa[1]=7sa[1]=7sa[1]=7,sa[2]=7−35=−28sa[2]=7-35=-28sa[2]=7−35=−28,sa[3]=−28+5=−23sa[3]=-28+5=-23sa[3]=−28+5=−23

b=[14,9,50]b = [14,9,50]b=[14,9,50],计算得:
sb[1]=14sb[1]=14sb[1]=14,sb[2]=14−9=5sb[2]=14-9=5sb[2]=14−9=5,sb[3]=5+50=55sb[3]=5+50=55sb[3]=5+50=55

询问1:(1,1)(1,1)(1,1) 到 (2,2)(2,2)(2,2)
sumA=sa[2]−sa[0]=−28sumA = sa[2]-sa[0] = -28sumA=sa[2]−sa[0]=−28,sumB=sb[2]−sb[0]=5sumB = sb[2]-sb[0] = 5sumB=sb[2]−sb[0]=5 → ans=−28×5=−140ans = -28 \times 5 = -140ans=−28×5=−140

询问2:(1,1)(1,1)(1,1) 到 (3,2)(3,2)(3,2)
sumA=sa[3]−sa[0]=−23sumA = sa[3]-sa[0] = -23sumA=sa[3]−sa[0]=−23,sumB=5sumB = 5sumB=5 → ans=−23×5=−115ans = -23 \times 5 = -115ans=−23×5=−115

与样例输出完全一致。

完整 C++ 代码

cpp 复制代码
#include <iostream>
using namespace std;
typedef long long ll;
const int M=1e5+10;
ll sa[M],sb[M],a[M],b[M];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int H,W,Q;
    cin>>H>>W>>Q;
    for(int i=1;i<=H;++i){
        cin>>a[i];
        sa[i]=sa[i-1]+(i%2?a[i]:-a[i]);
    }
    for(int i=1;i<=W;++i){
        cin>>b[i];
        sb[i]=sb[i-1]+(i%2?b[i]:-b[i]);
    }
    while(Q--){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        ll A=sa[x2]-sa[x1-1];
        ll B=sb[y2]-sb[y1-1];
        cout<<A*B<<'\n';
    }
    return 0;
}
相关推荐
我在人间贩卖青春1 天前
C++之继承与派生类的关系
c++·向上造型·向下造型
Trouvaille ~1 天前
【Linux】应用层协议设计实战(二):Jsoncpp序列化与完整实现
linux·运维·服务器·网络·c++·json·应用层
EmbedLinX1 天前
嵌入式之协议解析
linux·网络·c++·笔记·学习
wangjialelele1 天前
Linux中的进程管理
java·linux·服务器·c语言·c++·个人开发
历程里程碑1 天前
普通数组----轮转数组
java·数据结构·c++·算法·spring·leetcode·eclipse
李日灐1 天前
C++进阶必备:红黑树从 0 到 1: 手撕底层,带你搞懂平衡二叉树的平衡逻辑与黑高检验
开发语言·数据结构·c++·后端·面试·红黑树·自平衡二叉搜索树
汉克老师1 天前
GESP2025年6月认证C++二级( 第一部分选择题(1-8))
c++·循环结构·表达式·分支结构·gesp二级·gesp2级
rainbow68891 天前
C++高性能框架Drogon:后端开发新标杆
c++
Q741_1471 天前
C++ 优先级队列 大小堆 模拟 力扣 703. 数据流中的第 K 大元素 每日一题
c++·算法·leetcode·优先级队列·