1. 程式人生 > 實用技巧 >CSP/NOIP新賽制內部挑戰賽3 B. contest

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