2019南昌G
模数为合数,所以只有约3000个数字不为0
记录一下不为0的数字位置
H[x]代表距离为x的连续段的数字和的最大值
处理出H[x]
再H[x] = max(H[x],H[x-1])记录下前缀最大,
对每个询问二分答案
#include<bits/stdc++.h> using namespace std; #define int long long int n,q; int A[3004]; const int mod = 998857459; void init() { A[0]=1; for(int i=1;i<=3000;i++){ A[i]=(A[i-1]*i)%mod; } } int x; vector<int>v; int B[100005]; int H[100005]; int pre[3005]; signed main() { init(); scanf("%lld%lld",&n,&q); v.push_back(0); for(int i=1;i<=n;i++){ scanf("%lld",&x); if(x<=3000){ B[i]=A[x]; v.push_back(i); }else{ B[i]=0; } } for(int j=1;j<v.size();j++){ pre[j]=(B[v[j]]+pre[j-1])%mod; } for(int i=1;i<=v.size();i++){ for(int j=0;j+i-1<v.size();j++){ H[v[j+i-1]-v[j]+1]=max(H[v[j+i-1]-v[j]+1],(pre[j+i-1]-pre[j-1]+mod)%mod); } } for(int i=1;i<=n;i++){ H[i]=max(H[i],H[i-1]); } for(int i=1;i<=q;i++){ scanf("%lld",&x); int l = 1,r =n+1; while(l+1<=r){ int mid=(l+r)/2; if(H[mid]<x){ l= mid+1; }else r=mid; } if(l==n+1){ cout<<-1<<' '; }else{ cout<<l<<' '; } } }