1 条题解

  • 0
    @ 2025-8-24 22:36:33

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar TMM233
    **

    搬运于2025-08-24 22:36:33,当前版本为作者最后更新于2023-11-13 23:54:59,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这是一个构造题

    如果熟悉二分查找的话,我们可以注意到我们总是先搜索中点,再搜索左右区间:

    既然这样,那我们优先考虑把字符串中值为 true 的数字按照从小到大的顺序放在区间中点这样子,我们就可以保证这些数字二分查找的结果一定是正确的。

    代码如下

    	vector<ll> ton;// 用桶装 true 的项
            stack<ll> ton2;// 用桶装 false 的项
            ton.push_back(-1);
            vector<ll> ans(n+1,-1);
            for(int i=1;i<=n;i++)
            {
                if(s[i]=='1')
                ton.push_back(i);
                else
                ton2.push(i);
            }
            // 把字符串中值为 true 的数字按照从小到大的顺序放在区间中点
            auto build=[&](auto self,ll l,ll r,ll ton_l,ll ton_r)->void{
                if(ton_l>ton_r) return; 
                ll mid=(l+r)>>1;
                if(ton_l==ton_r)
                {
                    ans[mid]=ton[ton_l];
                    return;
                }
                ll ton_mid=(ton_l+ton_r)>>1;
                ans[mid]=ton[ton_mid];
                self(self,l,mid-1,ton_l,ton_mid-1);
                self(self,mid+1,r,ton_mid+1,ton_r);
            };
            build(build,1,n,1,ton.size()-1);
    

    之后我们考虑处理字符串中值为 false 的数字。题目中要求 S[p]1S[p]\le1,对此我们不一定需要找到最优解,只要保证 S[p]1S[p]\le1 即可。考虑将剩余的数字按从大到小的顺序填充进入剩下的空位,因为一个序列递增一个序列递减,那么最多就只能卡住一个数字,因此有 S[p]1S[p]\le1

    完整代码如下

    #include<bits/stdc++.h>
    using namespace std;
    #define mod 1000000007
    #define IOS ios::sync_with_stdio(0),cin.tie(0)
    typedef long long ll; 
    typedef pair<ll,ll> p;
    const int N=2e5+5;
    int main()
    {
        IOS;
        ll t;
        cin>>t;
        while(t--)
        {
            ll n;
            cin>>n;
            string s;
            cin>>s;
            s=' '+s;
            vector<ll> ton;// 用桶装 true 的项
            stack<ll> ton2;// 用桶装 false 的项
            ton.push_back(-1);
            vector<ll> ans(n+1,-1);
            for(int i=1;i<=n;i++)
            {
                if(s[i]=='1')
                ton.push_back(i);
                else
                ton2.push(i);
            }
            // 把字符串中值为 true 的数字按照从小到大的顺序放在区间中点
            auto build=[&](auto self,ll l,ll r,ll ton_l,ll ton_r)->void{
                if(ton_l>ton_r) return; 
                ll mid=(l+r)>>1;
                if(ton_l==ton_r)
                {
                    ans[mid]=ton[ton_l];
                    return;
                }
                ll ton_mid=(ton_l+ton_r)>>1;
                ans[mid]=ton[ton_mid];
                self(self,l,mid-1,ton_l,ton_mid-1);
                self(self,mid+1,r,ton_mid+1,ton_r);
            };
            build(build,1,n,1,ton.size()-1);
            for(int i=1;i<=n;i++)
            {
                if(ans[i]==-1)
                {
                    ans[i]=ton2.top();
                    ton2.pop();
                }
            }
            for(int i=1;i<=n;i++)
            {
                cout<<ans[i]<<(i==n?'\n':' ');
            }
        }
    }
    
    • 1

    信息

    ID
    7449
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者