尺取法;应用于有这么一类问题,需要在给的一组数据中找到不大于某一个上限的“最优连续子序列”
HDU5672
给你一个1e6的字符串,问你有多少个连续子串的至少包含不同的k个字母。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[1000005];
int c[30],k;
int main()
{
int t;scanf("%d",&t);
while(t--)
{
scanf("%s%d",s,&k);
memset(c,0,sizeof(c));
int l=0,r=0,cnt=0,len=strlen(s);
long long ans=0;
while(l<=r)
{
while(cnt<k&&r<len)
{
c[s[r]-'a']++;
if(c[s[r]-'a']==1) cnt++;
r++;
}
if(cnt<k) break;
ans+=(len-r+1);
c[s[l]-'a']--;
if(c[s[l]-'a']==0) cnt--;
l++;
}
printf("%lld\n",ans);
}
}
poj 3061
求连续子序列的和大于等于一个k值的最小区间长度。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int a[100005];
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int l=0,r=0,sum=0,ans=n+1;
while(l<=r)
{
while(r<n&&sum<k)
{
sum+=a[r];
r++;
}
if(sum<k) break;
ans=min(ans,r-l);
sum-=a[l++];
}
if(ans==n+1) puts("0");
else printf("%d\n",ans);
}
}
pku2100
给你一个n(1e14),求连续整数的和等于n.
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
vector<pair<int,int> > ans;
int main()
{
ll n;
scanf("%lld",&n);
ll l=1,r=1,sum=0;
while(l*l<=n)
{
while(r*r<=n&&sum<n)
{
sum+=r*r;
r++;
}
if(sum==n) {ans.push_back(make_pair(l,r));}
if(sum<n) break;
sum-=l*l;
l++;
}
printf("%d\n",(int)ans.size());
for(int i=0;i<ans.size();i++)
{
printf("%d",ans[i].second-ans[i].first);
for(int j=ans[i].first;j<ans[i].second;j++)
printf(" %d",j);
puts("");
}
}