1. 程式人生 > 其它 >2019.7.10 義烏模擬賽 T3 C

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');
	}
}