2019.7.10 义乌模拟赛 T3 C
一眼就感觉这个东西很APIO。
然后就真那道题的弱化版。
首先我们显然处理出每个点往右边跳能跳到哪里出\(k\)
因为\(a\)非负所以这个东西显然单调可以双指针指出来。
然后发现我们得到的是一个树形结构。于是愉快地树上倍增即可。
时间复杂度\(O((m+n)logn)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 1000000
#define M 30
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define IT set<ques>::iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,x,y,now,A[N+5],Q[N+5],R[N+5],fa[N+5][25],lg[N+5],r=1,ans;ll Sum[N+5],k;
I void read(int &x){
char s=getchar();x=0;while(s<'0'||s>'9') s=Gc();
while(s>='0'&&s<='9') x=x*10+s-48,s=Gc();
}
I void print(int x){x>9&&(print(x/10),0);putchar(x%10+48);}
int main(){
freopen("c.in","r",stdin);freopen("c.out","w",stdout);
re int i,j;scanf("%d%d%lld",&n,&m,&k);for(i=1;i<=n;i++) read(A[i]),Sum[i]=Sum[i-1]+A[i],Q[i]=Q[i-1]+(A[i]>k);
for(i=1;i<=n;i++){while(r<=n&&Sum[r]-Sum[i-1]<=k)r++;R[i]=(A[i]>k)?r:r-1;}for(i=2;i<=n;i++)lg[i]=lg[i/2]+1;
for(i=n;i;i--){
for(fa[i][0]=R[i],j=1;fa[i][j-1];j++) fa[i][j]=fa[fa[i][j-1]+1][j-1];
}
while(m--){
read(x);read(y);if(Q[y]-Q[x-1]>0){printf("Chtholly\n");continue;}
ans=0;now=x;for(i=lg[n-x+1];~i;i--) if(fa[now][i]&&fa[now][i]<=y) ans+=(1<<i),now=fa[now][i]+1;print(ans+(now!=y+1)),putchar('\n');
}
}