当日总结

小红定义一个长度为
4
4 的数组为“三带一”,当且仅当其包含三个相同的元素和另一个不同的元素。
现在小红拿到了一个长为
n
n 的数组,他想知道该数组最多包含多少个互不相交的“三带一”连续子数组,请你帮帮他。
输入描述:
第一行输入一个整数
n
(
4

n

2
×
1
0
5
)
n(4≦n≦2×10
5
) 。
第二行输入
n
n 个整数
a1,a2,…,an(1≦ai≦2×105)
a 1,a 2 ,…,a n
​(1≦a i ≦2×10
5
) 代表数组的元素。
输出描述:
输出一个整数,代表“三带一”连续子数组的数量。
原代码 #include

include

include

using namespace std;
using ll=long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll n;
cin>>n;
map<ll,int>cnt_map;
vectornum(n);
for(ll i=0;i<n;i++)
{
cin>>num[i];
}
ll cnt=0;
for(ll i=0;i<n-3;i+=4)
{
ll j=i+3;
cnt_map.clear();
for(ll k=i;k<=j;k++)
{
cnt_map[num[k]]++;

   }
   for(ll m=i;m<=j;m++)
   {
    if(m==i)
    {
        if(cnt_map[num[m]]==3)cnt++;
    }
    else
    {
    if(cnt_map[num[m]]==cnt_map[num[m-1]]||cnt_map[num[m]]==cnt_map[num[m-2]]||cnt_map[num[m]]==cnt_map[num[m-3]])continue;
      if(cnt_map[num[m]]==3)cnt++;
    }
   }
}
cout<<cnt<<endl;
return 0;

}
核心问题
“三带一” 判断逻辑完全错误
通过 “元素计数等于 3” 就计数,但没验证 “是否只有一个元素出现 3 次、另一个出现 1 次”(比如子数组 [1,1,1,1] 中每个元素计数都是 4,本应不算,但你的逻辑会误判;而 [1,1,1,2] 会因 3 个 1 被重复计数);
内层 for(m) 循环完全多余,同一个 4 长度子数组会被多次计数(比如 [1,1,1,2] 会被计数 3 次)。
遍历逻辑有漏洞
i +=4 意味着只检查 0-3、4-7、8-11… 这些位置的子数组,但如果某个非 4 倍数起始位置的子数组是 “三带一”(比如 1-4),且前面 0-3 不是,你的代码会直接跳过,导致漏统计(贪心策略应是 “找到一个就跳 4 步,没找到就跳 1 步”,而非直接按 4 步遍历)。
效率问题
map 比 unordered_map 慢,统计 4 个元素的计数完全没必要用 map;
内层多余的 for(m) 循环增加无意义的计算。
正确代码#include

include

include <unordered_map> // 替换map,提升效率

using namespace std;
using ll = long long;

int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

ll n;
cin >> n;
vector<ll> num(n);
for (ll i = 0; i < n; ++i) {
    cin >> num[i];
}

ll cnt = 0;
ll i = 0;
// 贪心遍历:找到三带一则跳4步,否则跳1步
while (i <= n - 4) {
    unordered_map<ll, int> cnt_map; // 仅在当前窗口创建,无需clear
    // 统计当前4个元素的计数
    for (ll k = i; k < i + 4; ++k) {
        cnt_map[num[k]]++;
    }

    // 正确判断“三带一”:恰好一个元素3次,一个元素1次
    int has3 = 0, has1 = 0;
    bool isValid = true;
    for (auto& p : cnt_map) {
        if (p.second == 3) has3++;
        else if (p.second == 1) has1++;
        else { // 出现2次/4次等,直接不合法
            isValid = false;
            break;
        }
    }

    // 满足条件则计数+1,并跳4步(互不相交)
    if (isValid && has3 == 1 && has1 == 1) {
        cnt++;
        i += 4;
    } else {
        i++; // 不满足则右移1步继续找
    }
}

cout << cnt << endl;
return 0;

}

posted @ 2026-03-19 22:24  lagranSun  阅读(3)  评论(0)    收藏  举报