博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

BZOJ:4209: 西瓜王

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4209

 

(虽然仅仅是看在名字的份上,我们还是得说这题是一道)

绝世好题!西瓜王!西瓜王!西瓜王![wàng]

说点正经的,一开始以为合成圣堂的时候必须相邻的,然后变成了区间内取k个数不能相邻的数的最大总价值,诶我的瓜妈妈呀,不会做啊……

看一下CA爷blog:贪心,然后替换……

诶,我看错题了?

最后就是主席树维护一下区间前k大的总价值,再查一下这最大的k个里面有多少个奇数多少偶数,如果奇数数量是奇数的话(好拗口)那就再查一下在前k大的数中最小的奇数和偶数,不在前k大中最大奇数和偶数,然后替换一下就吼了啊。。。

卡常卡不过啊T_T

#include<cstdio>
#include<algorithm>
#define MN 300001
#define ll long long
using namespace std;
 
char ibuf[20000004],*iptr=ibuf-1,C;
inline int _(){
    int x=0,c=*++iptr;
    while(c<48)c=*++iptr;
    while(c>47)x=x*10+c-48,c=*++iptr;
    return x;
}
char obuf[5000000],*optr=obuf;
inline void _(ll x){
    static int stk[32],stp=0;
    if (x<0) *(optr++)='-',x=-x;
    if(!x)stk[stp++]=0;
    while(x)stk[stp++]=x%10,x/=10;
    while(stp)*(optr++)=stk[--stp]+48;
    *(optr++)=10;
}
struct tree{int l,r,s[2],S;ll al;}t[MN*40];
int n,m,a[MN],num=0,l,r,k,s[2],S[MN][2],ro[MN],mi,ma;
ll mmh,c;
inline ll min(ll a,ll b){return a<b?a:b;}
inline ll max(ll a,ll b){return a>b?a:b;}
void in(int &P,int x,int v){
    int l=mi,r=ma,mid,*p;p=&P;
    for (;;){
        *p=++num;t[*p]=t[x];t[*p].s[v&1]++;t[*p].S++;t[*p].al+=v;
        if (l==r) break;
        int mid=l+r>>1;
        if (v<=mid) p=&t[*p].l,x=t[x].l,r=mid;else p=&t[*p].r,x=t[x].r,l=mid+1;
    }
}
void ask(int p,int x,int l,int r,int k){
    while (l<r){
        if (k>=t[t[p].r].S-t[t[x].r].S) s[0]+=t[t[p].r].s[0]-t[t[x].r].s[0],s[1]+=t[t[p].r].s[1]-t[t[x].r].s[1],
        mmh+=t[t[p].r].al-t[t[x].r].al,k-=t[t[p].r].S-t[t[x].r].S,p=t[p].l,x=t[x].l,r=l+r>>1;else p=t[p].r,x=t[x].r,l=(l+r>>1)+1;
        if (k==0) return;
    }
    if (k) mmh+=1LL*k*l,s[l&1]+=k;
}
ll askmax(int p,int x,int k,bool bo){
    if (t[p].s[bo]-t[x].s[bo]<=k) return -1e18;
    int l=mi,r=ma;
    while (l<r)
    if (t[t[p].r].s[bo]-t[t[x].r].s[bo]>k) p=t[p].r,x=t[x].r,l=(l+r>>1)+1;else k-=t[t[p].r].s[bo]-t[t[x].r].s[bo],p=t[p].l,x=t[x].l,r=l+r>>1;
    return l;
}
ll askmin(int p,int x,int k,bool bo){
    if (t[p].s[bo]-t[x].s[bo]<k) return 1e18;
    int l=mi,r=ma;
    while (l<r)
    if (t[t[p].r].s[bo]-t[t[x].r].s[bo]>=k) p=t[p].r,x=t[x].r,l=(l+r>>1)+1;else k-=t[t[p].r].s[bo]-t[t[x].r].s[bo],p=t[p].l,x=t[x].l,r=l+r>>1;
    return l;
}
int main(){
    ibuf[fread(ibuf,1,20000000,stdin)]=0;
    register int i;
    n=_();t[0].l=t[0].r=t[0].s[0]=t[0].s[1]=t[0].al=t[0].S=0;
    for (i=1;i<=n;i++) a[i]=_(),S[i][0]=S[i-1][0],S[i][1]=S[i-1][1],S[i][a[i]&1]++,mi=min(mi,a[i]),ma=max(ma,a[i]);
    for (i=1;i<=n;i++) in(ro[i],ro[i-1],a[i]);
    m=_();
    while (m--){
        l=_();r=_();k=_();
        if ((S[r][0]-S[l-1][0]>>1)+(S[r][1]-S[l-1][1]>>1)<(k>>1)){_(-1);continue;}
        mmh=s[0]=s[1]=0;ask(ro[r],ro[l-1],mi,ma,k);
        if (s[0]&1) mmh-=min(askmin(ro[r],ro[l-1],s[1],1)-askmax(ro[r],ro[l-1],s[0],0),askmin(ro[r],ro[l-1],s[0],0)-askmax(ro[r],ro[l-1],s[1],1));
        _(mmh);
    }
    fwrite(obuf,1,optr-obuf,stdout);
    return 0;
}
View Code

 

posted @ 2017-04-18 07:20  swm_sxt  阅读(291)  评论(0编辑  收藏  举报