CSUOJ 1411 Longest Consecutive Ones

来源:互联网 发布:薛之谦女装店淘宝店 编辑:程序博客网 时间:2024/06/15 09:00
转自:http://www.cnblogs.com/CSU3901130321/p/4202539.html题目大意:希望在 k 步之内,将尽可能多的1移到相邻的位置上这里依靠前缀和解决问题我们用pos[i]保存第i个1的位置,这里位置我以1开始用sum[i]保存前 i 个10 点移到当前位置所需的步数每次进行判断能否将 st 号 到 la 号的1移到相邻位置,我们要先清楚,为了使移动步数最少,我们需要固定中间的数保持它的位置不动,将两边的数向它靠拢那么移动的步数就分为左右两侧中间的数编号为 m = (st + la)>> 1首先将左侧移到中间,将 m 也作为其中的一部分,我们先将这 (m-st+1)个数均移到 pos[m]的位置上,而原本已经移好了 sum[m] - sum[st-1]个位置因为是相邻,所以要把都在pos[m]上的位置一个个左移,分别左移 012 。。。。到(m-st)所以左半部分为 (ll)pos[m]*(m-st+1) - (sum[m] - sum[st-1])- (ll)(m-st+1)*(m-st)/2 ;右半部分同样道理,但是这回是因为其本身所在位置更大,所以是(sum[la] - sum[m-1]) - (ll)pos[m]*(la-m+1) - (ll)(la-m+1)*(la-m)/2 ;#include <iostream>#include <cstring>#include <queue>#include <stdlib.h>#include <stdio.h>#include <algorithm>#include <cmath>using namespace std;const int MAX=100005;char Str[MAX];int K,Pos[MAX];long long Sum[MAX];bool Check(int Start,int Len){    int End=Start+Len-1;    int Middle=(Start+End)/2;    long long Cost=0;    Cost+=(long long)Pos[Middle]*(Middle-Start+1)-(Sum[Middle]-Sum[Start-1])-(long long)(Middle-Start+1)*(Middle-Start)/2;    Cost+=(Sum[End]-Sum[Middle-1])-(long long)Pos[Middle]*(End-Middle+1)-(long long)(End-Middle+1)*(End-Middle)/2;    if(Cost>K) return false;    return true;}int main(){    cin.sync_with_stdio(false);    int T;    cin>>T;    Sum[0]=0;    while(T--)    {        cin>>(Str+1)>>K;        int len=strlen(Str+1),cnt=0;        for(int i=1;i<=len;i++)            if(Str[i]=='1')                Pos[++cnt]=i;        for(int i=1;i<=cnt;i++)            Sum[i]=Sum[i-1]+Pos[i];        int Ans=1,Start=1;        while (Start+Ans-1<=cnt)        {            if (Check(Start,Ans))                Ans++;            else                Start++;        }        cout<<Ans-1<<endl;    }    return 0;}
0 0
原创粉丝点击