我的:尺取法,l从0开始,r递增首先找到符合的,之后随着r的增大,判断是否会对区间的有效个数产生影响,有的话r递增,知道找到使有效个数符合的r.
其中的set使为了找到不重复的个数,利用了set元素的不重复性。
我的:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<deque>
#include<list>
#include<cmath>
using namespace std;
const int maxn=100000+10;
typedef long long ll;
int main()
{
int n;
while(~scanf("%d",&n))
{
set<char >se;
map<char ,int >m;
char s[maxn];
scanf("%s",s);
for(int i=0;i<n;i++)
{
se.insert(s[i]);
}
int len=se.size();
int l=0,r=0;
int cnt=0,ans=n;
while(l<n)
{
while(cnt<len&&r<n)
{
if(m[s[r]]==0)
cnt++;
m[s[r]]++;
r++;
}//r的值只能是不变或者越来越大,所以可以不变
if(cnt<len)//如果上面这个循环是由于r>=n而出来的话,就说明已经到了最后一个值,跳出就行了。
break;
ans=min(ans,r-l);//cout<<ans<<"sdfhj "<<s+l<<endl;
if(--m[s[l]]==0)//l往后推,判断一下s[l]是否对cnt贡献了值,如果贡献了就要减去。
cnt=cnt-1;
l++;
}
printf("%d\n",ans);
}
return 0;
}
题意:一个n大小的只含0,1的数列,然后可以有k次机会把0变成1,求使得变化后的数列的连续的1的最大个数,然后输出变化后的序列;
思路:因为要使得数列中连续的1的个数最大,就说明变化的k个0必须是连续的,我把所有的0都记录一下,然后进行在所有0中取连续的k个0,进行尺取就行了;
#include<bits/stdc++.h>
using namespace std;
const int maxn = 300000 + 10;
struct Node
{
int point;//记录0的位置
int l;//0节点的左边连续的1的个数
int r ;//0节点的右边的连续的1的个数
}a[maxn];
int b[maxn];
int main()
{
int n,k;
while( ~ scanf("%d%d",&n,&k) )
{
for(int i = 0; i < n ; i ++)
scanf("%d",&b[i]);
int len = 0;
int temp = 0;
for(int i = 0; i < n ; i ++)
{
if(b[i] == 0)
{
a[len].point = i;
a[len ++].l = i - temp;
temp = i + 1;
}
}
a[len - 1].r = n - a[len - 1].point - 1;
for(int i = 0; i < len - 1; i ++)
{
a[i].r = a[i + 1].l;
}
if(len == 0 || k >= len)//特判
{
cout << n << endl;
for(int i = 0 ; i < n ; i ++)
if(i < n - 1)
cout << b[i] <<" ";
else cout << b[i] << endl;
continue;
}
if(k == 0 && len )//特判
{
int ans = 0;
for(int i = 0 ; i < len ; i ++)
{
if(a[i].l > ans)
ans = a[i].l;
}
if(a[len - 1].r > ans)
ans = a[len - 1].r;
cout << ans << endl;
for(int i = 0; i < n ; i ++)
if(i < n - 1)
cout << b[i] <<" ";
else cout << b[i] << endl;
continue;
}
int ll = 0, rr = 0;
int sum = 0,ans = 0;
int cnt = 0;
int x = 0, y = k - 1;
while(ll < len)//尺取法
{
while(cnt < k && rr <= len)
{
sum += a[rr].l;
rr ++;
cnt ++;
if(cnt == k)
{
sum += a[rr - 1].r;
}
}
if(rr > len)
break;
if(sum > ans)
{
ans = sum;
x = ll;
y = rr - 1;
}
sum -= a[ll].l;
sum -= a[rr - 1].r;
cnt --;
ll ++;
}
cout << ans + k<< endl;
for(int i = x ; i <= y; i ++)
{
b[a[i].point] = 1;
}
for(int i = 0;i < n ;i ++)
if(i < n - 1)
cout << b[i] << " ";
else cout << b[i] << endl;
}
return 0;
}