1 条题解

  • 1
    @ 2025-9-16 14:38:06

    参考题解

    先统计初始位置 R 左侧连续锁定的门数量(l)和右侧连续锁定的门数量(r),这些连续锁定的门无需额外操作即可保持状态;剩余需处理的是 “左侧连续锁定结束” 到 “右侧连续锁定开始” 的中间区域。处理时根据 l 和 r 的大小选择方向(l 更大则从左到右,否则从右到左),对中间区域中初始解锁的门(0)只需 1 次切换,初始锁定的门(1)因需先解锁通行再重新锁定,故需 2 次切换,最终累加得到最小操作次数,通过优先处理更长连续锁定区域减少移动带来的额外操作,时间复杂度为 O (n)。

    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <deque>
    #include <unordered_map>
    #include <map>
    #include <cstring>
    #include <cmath>
    #include <unordered_set>
    #include <set>
    #include <utility>
    #include <climits>
    #include <iomanip>
    #include <stack>
    #include <bitset>
    
    #define int long long
    #define PII pair<int, int> 
    #define TLLL tuple<int , int , int>
    #define INF 0x3f3f3f3f3f3f3f3f
    #define inf 0x3f
    #define all(v) v.begin() + 1 , v.end()
    #define ALL(v) v.begin() , v.end()
    #define endl "\n"
    using namespace std;
    
    void solve()
    {
        int n , R;
        cin >> n >> R;  // 输入门的数量n和初始房间R
    
        vector<int> vec(n + 1);  // 用1-based数组存储门的状态(vec[i]对应第i扇门)
        for (int i = 1 ; i <= n ; i ++ ) cin >> vec[i];  // 输入每扇门的初始状态(0解锁,1锁定)
    
        // 统计右侧连续已锁定的门数量(从最右侧门开始,仅限初始位置R右侧的门)
        int l = 0 , r = 0;  // l:左侧连续锁定门数;r:右侧连续锁定门数
        // 从最后一扇门(n)向左遍历,直到R+1(初始房间右侧第一扇门)
        for (int i = n ; i >= R + 1 ; i -- ) 
            if (vec[i]) r ++;  // 门已锁定则计数+1
            else break;  // 遇到未锁定的门则停止统计(右侧连续锁定中断)
    
        // 统计左侧连续已锁定的门数量(从最左侧门开始,仅限初始位置R左侧的门)
        // 从第一扇门(1)向右遍历,直到R(初始房间左侧最后一扇门)
        for (int i = 1 ; i <= R ; i ++ ) 
            if (vec[i]) l ++ ;  // 门已锁定则计数+1
            else break;  // 遇到未锁定的门则停止统计(左侧连续锁定中断)
    
        int ans = 0;
        // 根据左右连续锁定门的数量决定处理顺序(优先处理连续锁定更长的一侧,减少移动成本)
        if (l > r) 
        {
            // 左侧连续锁定更长,从左向右处理中间区域的门
            // 中间区域:左侧连续锁定结束的下一扇门(l+1)到右侧连续锁定开始的前一扇门(n-r)
            for (int i = l + 1 ; i <= n - r ; i ++) 
                if (vec[i]) ans += 2;  // 若门已锁定,需先解锁(移动到门旁)再锁定,共2次操作
                else ans += 1;  // 若门未锁定,直接锁定,1次操作
            cout << ans << endl;
        }
        else 
        {
            // 右侧连续锁定更长或相等,从右向左处理中间区域的门
            for (int i = n - r ; i >= l + 1 ; i -- )
                if (vec[i]) ans += 2;  // 已锁定的门需先解锁再锁定,2次操作
                else ans += 1;  // 未锁定的门直接锁定,1次操作
            cout << ans << endl;
        }
    
        return ;
    }
    
    
    signed main() 
    {
        ios::sync_with_stdio(false);
        cin.tie(nullptr), cout.tie(nullptr);
        int T = 1;
        // cin >> T;
        while (T -- ) solve();
        return 0;
    }
    
    
    
    • 1

    信息

    ID
    5616
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    递交数
    44
    已通过
    3
    上传者