P12708 [KOI 2021 Round 1] 分割

题解描述

该题目要求将给定整数序列分割成四个连续的非空部分,且每个部分的和相等。关键在于如何高效地统计所有满足条件的分割方式。

方法思路

  1. 总和检查:首先计算整个序列的总和。如果总和不能被4整除,则无法分割,直接返回0。

  2. 前缀和预处理:使用前缀和数组 pre 记录到每个位置为止,可以形成第一个分割点的次数。即,如果从开始到当前位置的前缀和等于总和的四分之一,则该位置可以作为第一个分割点。

  3. 后缀和预处理:同样,使用后缀和数组 suf 记录从末尾到当前位置的和等于总和的四分之一的次数,用于标识第三个分割点后的部分。

  4. 中间分割点统计:遍历所有可能作为第二个分割点的位置,检查前半部分的和是否等于总和的一半。如果是,则将该位置的前缀计数和后缀计数相乘,累加到结果中,得到所有可能的分割方式。

  • pre[i] 表示:切割在i和i+1之间作为第一个分割点的可能性数量
  • suf[i] 表示:切割在i和i+1之间作为第三个分割点的可能性数量
    A1 A2 ... Ai | Ai+1 ... Aj | Aj+1 ... Ak | Ak+1 ... AN
     ↑           ↑ ↑           ↑ ↑           ↑ ↑
    第一个分割点  第二个分割点  第三个分割点  第四个分割点(固定为N)
    • 第一个分割点:在位置i(切割在i和i+1之间)

    • 第二个分割点:在位置j(切割在j和j+1之间)

    • 第三个分割点:在位置k(切割在k和k+1之间)

解决代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10,inf = 0x3f3f3f3f;
ll s[N],a[N],n; // s数组是前缀和数组,a数组存储原始数据,n是数据个数
ll pre[N],suf[N]; // pre数组记录前i个位置中能作为第一个分割点的次数,suf数组记录后i个位置中能作为第三个分割点的次数
ll ans; // 存储最终答案

int main()
{
    cin >> n; // 输入数据个数n
    for(int i = 1; i <= n; i++) cin >> a[i],s[i] = s[i - 1] + a[i]; // 输入数据并计算前缀和
    if(s[n] % 4) { // 如果总和不能被4整除,直接输出0
        cout << 0;
        return 0;
    }
    ll sum = 0; // 临时变量,用于累计和
    for(int i = 2; i <= n; i++) // 从第二个位置开始遍历到最后一个位置
    {
        sum += a[i - 1]; // 累计到前一个位置的和
        if(sum == s[n] / 4) pre[i] = pre[i - 1] + 1; // 如果累计和等于总和的1/4,则当前位置可以作为第一个分割点,pre[i]增加1
        else pre[i] = pre[i - 1]; // 否则保持前一个值
    }
    sum = 0; // 重置临时变量
    for(int i = n - 1; i >= 1; i--) // 从倒数第二个位置遍历到第一个位置
    {
        sum += a[i + 1]; // 累计到后一个位置的和
        if(sum == s[n] / 4) suf[i] = suf[i + 1] + 1; // 如果累计和等于总和的1/4,则当前位置可以作为第三个分割点,suf[i]增加1
        else suf[i] = suf[i + 1]; // 否则保持后一个值
    }
    sum = 0; // 再次重置临时变量
    for(int i = 1; i <= n - 1; i++) // 遍历所有可能作为第二个分割点的位置
    {
        sum += a[i]; // 累计到当前位置的和
        if(sum == s[n] / 2) ans += pre[i] * suf[i + 1]; // 如果累计和等于总和的1/2,则前半部分可以分成两个等和部分,此时将pre[i]和suf[i+1]的乘积加到答案中
    }
    cout << ans; // 输出答案
    return 0;
}

 

posted @ 2025-08-29 11:25  CRt0729  阅读(8)  评论(0)    收藏  举报