BZOJ 3721 Final Bazarek

用队列的时候不要思想僵化。这题具有决策单调。

#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('
');
        return;
    }
    int cnt=0;
    while (x){
        sta[++cnt]=x%10;
        x/=10;
    }
    while (cnt){
        putchar('0'+sta[cnt]);
        cnt--;
    }
    putchar('
');
}
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;
}
原文地址:https://www.cnblogs.com/ziliuziliu/p/6604908.html