CSP/NOIP新赛制内部挑战赛3 B. contest
考虑维护一个类似链式的结构,去维护i位置为起点的一组将到哪里,然后一直跳下去就好
想到这里,自然就会考虑到用倍增去优化
这个倍增的预处理要从n倒着枚举
因为它都是向后跳的,要先把后面的算出来啊!! WA了两发
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=3e5+10; int n,t,x,a[maxn],pos[maxn][20]; ll v[maxn][20]; ll sum[maxn]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d%d",&n,&t,&x); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int j=1; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; for(int i=1;i<=n;i++) { while(j<n && sum[j]-sum[i-1]<t) j++; pos[i][0]=j; v[i][0]=j-i+1; } for(int i=n;i>=1;i--) for(int j=1;j<=19;j++) { if(pos[i][j-1]+x+1>n || !pos[pos[i][j-1]+x+1][j-1]) break; pos[i][j]=pos[pos[i][j-1]+x+1][j-1]; v[i][j]=v[i][j-1]+v[pos[i][j-1]+x+1][j-1]; } int l,r,q; ll ans=0; scanf("%d",&q); for(int i=1;i<=q;i++) { ans=0; scanf("%d%d",&l,&r); int j=l; for(int k=19;k>=0;k--) { if(j>n) break; if(pos[j][k]>r || !pos[j][k]) continue; ans+=v[j][k]; j=pos[j][k]+x+1; } if(j<=r) ans+=r-j+1; printf("%lld\n",ans); } return 0; }