用队列的时候不要思想僵化。这题具有决策单调。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1000050 using namespace std; long long n,m,x,f[maxn],g[maxn],dp[maxn],t1=0,t2=0,q[maxn],l=1,r=1,pos[maxn]; int sta[maxn]; long long read() { char ch;long long data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } void write(long long x){ if (x<0){ putchar('-'); x=-x; } if (!x){ putchar('0'); putchar('\n'); return; } int cnt=0; while (x){ sta[++cnt]=x%10; x/=10; } while (cnt){ putchar('0'+sta[cnt]); cnt--; } putchar('\n'); } bool cmp(const long long &x,const long long &y) {return x>y;} long long calc(long long x,long long y) {return f[y]+g[x-y];} long long get_pos(long long x) { long long left=l,right=r,mid,ans=-1; while (left<=right) { mid=(left+right)>>1; if (pos[q[mid]]<=x) {ans=q[mid];left=mid+1;} else right=mid-1; } return ans; } long long get_di(long long l,long long r,long long x,long long y) { long long mid,ans=l-1; while (l<=r) { mid=(l+r)>>1; if (calc(mid,x)>calc(mid,y)) {ans=mid;l=mid+1;} else r=mid-1; } return ans+1; } int main() { n=read(); for (long long i=1;i<=n;i++) { x=read(); if (x&1) f[++t1]=x;else g[++t2]=x; } if (!t1) for (long long i=1;i<=n;i++) dp[i]=-1; else { sort(f+1,f+t1+1,cmp);sort(g+1,g+t2+1,cmp); for (long long i=1;i<=t1;i++) f[i]+=f[i-1];for (long long i=1;i<=t2;i++) g[i]+=g[i-1]; l=r=1;q[l]=1;dp[1]=f[1];pos[1]=1; for (long long i=2;i<=n;i++) { while (l<=r && i-q[l]>t2) l++; if (i&1 && i<=t1) { while (l<=r && pos[q[r]]>=i && calc(pos[q[r]],i)>calc(pos[q[r]],q[r])) r--; if (l>r) q[++r]=i; else { long long ret=get_di(max(i,pos[q[r]]),i+t2,q[r],i); if (ret==-1) ret=max(ret,t2+q[r]); if (ret!=-1 && ret<=n) {q[++r]=i;pos[i]=ret;} } } if (l>r) dp[i]=-1; else dp[i]=calc(i,get_pos(i)); } } m=read(); for (long long i=1;i<=m;i++) {x=read();write(dp[x]);} return 0; }