思路:用倍增思维来写。dp[i][j]表示从i开始吧序列分为2^j 段最多到哪。那么初始化就是dp[n+1][i]=n+1(他从n开始后面长度为2^i 中大于整个序列之和+k的位置是n+1)得到dp[i][j]=dp[dp[i][j-1]][j-1]
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>
#include <sstream>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<cctype>
#include<cstring>
#include<cstdlib>
#define MAXX 100005
#define SIS std::ios::sync_with_stdio(false)
#define ll long long
#define INF 0x3f3f3f3f
//#include<bits/stdc++.h>
using namespace std;
const int MAX =1e6+20;
const double PI = 3.14159265359;
//const int mod = 1e9 + 7;
ll a[MAX],b[MAX];
vector<int> vt[200005];
ll dp[MAX][25],dep[200005];
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=b[i-1]+a[i];
}
for(int i=0;i<=21;i++)
{
dp[n+1][i]=n+1;
}
for(int i=n;i>=1;i--)
{
dp[i][0]=upper_bound(b+1,b+1+n,b[i-1]+k)-b;
for(int j=1;j<=21;j++)
dp[i][j]=dp[dp[i][j-1]][j-1];
}
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
ll cnt=0;
for(int i=21;i>=0;i--)
{
if(dp[l][i]<=r) cnt+=(1<<i),l=dp[l][i];
}
if(dp[l][0]>r)printf("%lld\n",cnt+1);
else
printf("Chtholly\n");
}
return 0;
}