先是想到直接暴力贪心分段,从l到r一个个枚举,如果<=k就不分
这样的时间复杂度是
O
(
m
n
)
O(mn)
O(mn)期望得分30pts
while(m--)
{
ll r,l;l=read();r=read();
ll ans=1;
bool pd=0;
ll z=l;
for(int i=l;i<=r;i++)
{
if(a[i]>k){pd=1;break;}
if(sum[i]-sum[z-1]>k)ans++,z=i;
}
if(pd)printf("Chtholly\n");
else printf("%d\n",ans);
}
在看数据表可以看到,当a[i]=1的数据有两个,则ans=(r-l+1)/k
期望得分50分
while(m--)
{
ll r,l;l=read();r=read();
ll kk=r-l+1;
if(kk%k==0) printf("%d\n",kk/k);
else printf("%d\n",kk/k+1);
}
100pts
因为是在一个个枚举的时候超时的,所以我们可以考虑能不能跳跃式地去找,这样就不会超时了。因此我们可以想到倍增
设 f [ i ] [ j ] 表 示 第 j 个 点 跳 1 < < i 此 可 以 跳 到 哪 里 f[i][j]表示 第 j 个点 跳 1<<i 此可以跳到哪里 f[i][j]表示第j个点跳1<<i此可以跳到哪里
倍增的转移就是 f [ i ] [ j ] = f [ i − 1 ] [ m i n ( n , f [ i − 1 ] [ j ] ) ] ; f[i][j]=f[i-1][min(n,f[i-1][j])]; f[i][j]=f[i−1][min(n,f[i−1][j])];
while(m--)
{
int ans=0;
int l,r;l=read();r=read();
if(sum[r]-sum[l-1]){puts("Chtholly");continue;}
for(int i=24;i>=0;i--)//倍增地去寻找
if(f[i][l]<=r)ans+=1<<i,l=f[i][l];
printf("%d\n",ans+1);
}