1955E-Long Inversions

题目链接:Long Inversions

首先我们可以考虑暴力的做法:

先从大到小枚举k的长度,然后每次遍历一遍数组,如果当前数字为0,那么就将[ i , i + k )这段区间都翻转一遍,那么时间复杂度为 O( n*n*k ),大概是n的三次方。

那么可以考虑优化一下:

既然要将[ i , i + k )这段区间都翻转一遍,那么我们可以用cnt记录当前位置需要翻转的次数,endc[]数组来表示翻转的结束位置,从i开始遍历时,假设a[i]=0那么cnt=1,那么记录endc[i+k]=1,

那么当我枚举到第i+k的位置时cnt-=end[i](此时的i是之前的i+k位置)那么之后的cnt=0。相当于计数器。那么这样总的时间复杂度就是O(n*n)。

代码附上:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N =5005;
int a[N];
int endc[N*2];//表示结束位置需要减去的次数
int n;

void solve(){
    cin>>n;
    string s;cin>>s;

    for(int k=n;k>=1;k--){//枚举长度
        for(int i=1;i<=n;i++)a[i]=s[i-1]-'0';
        memset(endc,0,sizeof(endc));
        int cnt=0;//表示当前位置需要翻转的次数
        for(int i=1;i<=n;i++){
            cnt-=endc[i];//[i,i+k)这段加,那么枚举到i+k这个位置要减去之前加的
            a[i]^=(cnt&1);//翻转过后的a[i]
            if(a[i]==0){
                if(i+k<=n+1){//n+1是因为[i,i+k)枚举到的是i+k-1<=n
                    a[i]=1;
                    endc[i+k]++;
                    cnt++;//翻转次数+1
                }
                else break;//如果枚举的长度超出范围
            }
        }

        bool flag=true;
        for(int i=1;i<=n;i++){
            if(a[i]==0)flag=false;
        }
        if(flag){
            cout<<k<<"\n";
            return;
        }

    }

}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while(t--){
        solve();
    }

    return 0;
}

  • 21
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值