zoukankan      html  css  js  c++  java
  • bzoj4209: 西瓜王

    Description

    西瓜王xgw最近喜欢上了玩星际争霸,很神的他尤其喜欢玩神族。有一天他生产了非常多的高阶圣堂和黑暗圣堂,并把他们排成了一条直线。
    但是他觉得这些东西奇形怪状的很不好看,于是他想把他们全都变成末日执政官和黑暗执政官那样的圆圆的像西瓜一样的东西。但是他的人口上限不够了……他只能从中选出一些来变成执政官。
    但是他玩的星际争霸有点特别,每一个圣堂有一个x值x_i,若x_i为奇数则他为高阶圣堂,否则为黑暗圣堂。而x值越大会使得合成以后的执政官更圆(TAT实在没啥好说的了)。xgw自然是想使得x值的和最大啦。
    xgw毕竟也是一个王,所以他很任性。他每次会在屏幕上随便框一下(也就是搞一个区间),然后问你这个区间要合成k个执政官选出的圣堂的x值之和最大值是多少。
    p.s.两个高阶圣堂可以合成一个末日执政官,两个黑暗圣堂可以合成一个黑暗执政官

    Input

    第一行一个整数n表示圣堂的个数。
    第二行n个整数表示每个圣堂的x值。
    第三行一个整数T表示xgw框了多少次。
    接下来T行每行三个整数l,r,k代表要从[l, r]这段区间里选出k个圣堂去合成k/2个执政官,保证k是偶数。

    Output

    输出T行,对于xgw每框一次输出选出的圣堂的x值之和最大值。若没有可行的选择方案则输出-1

    离散化后用可持久化线段树维护区间内的数,贪心选最大的k个值,若不合法则考虑贪心用一个奇数换掉一个偶数或用偶数换掉奇数

    #include<cstdio>
    #include<algorithm>
    #define G *++ptr
    typedef long long i64;
    const int N=3e5+7,inf=0x3f3f3f3f;
    char buf[N*100],*ptr=buf-1;
    int _(){
        int x=0,c=G;
        while(c<48)c=G;
        while(c>47)x=x*10+c-48,c=G;
        return x;
    }
    int n,q,rt[N],ch[N*25][2],sz[N*25][2],p=0,xs[N],id[N],ir[N];
    i64 sum[N*25];
    int ins(int w,int x,int v){
        int u=++p,u0=u,a=v&1;
        sz[u][a]=sz[w][a]+1;
        sz[u][a^1]=sz[w][a^1];
        sum[u]=sum[w]+v;
        for(int i=20,d;~i;--i){
            d=x>>i&1;
            ch[u][d^1]=ch[w][d^1];
            u=ch[u][d]=++p;w=ch[w][d];
            sz[u][a]=sz[w][a]+1;
            sz[u][a^1]=sz[w][a^1];
            sum[u]=sum[w]+v;
        }
        return u0;
    }
    int _a,_x,_v;
    void getpv(int w1,int w2,int L,int R){
        if(_v||sz[w1][_a]==sz[w2][_a])return;
        if(L==R&&R<=_x){
            _v=L;
            return;
        }
        int M=L+R>>1;
        if(_x>M)getpv(ch[w1][1],ch[w2][1],M+1,R);
        getpv(ch[w1][0],ch[w2][0],L,M);
    }
    void getnx(int w1,int w2,int L,int R){
        if(_v||sz[w1][_a]==sz[w2][_a])return;
        if(L==R&&L>=_x){
            _v=L;
            return;
        }
        int M=L+R>>1;
        if(_x<=M)getnx(ch[w1][0],ch[w2][0],L,M);
        getnx(ch[w1][1],ch[w2][1],M+1,R);
    }
    void query(int l,int r,int k){
        if(r-l+1<k){
            puts("-1");
            return;
        }
        i64 ss=0;
        int w1=rt[r],w2=rt[l-1],c0=0,c1=0,v=0;
        for(int i=20;~i;--i){
            int u1=ch[w1][1],u2=ch[w2][1];
            int s0=sz[u1][0]-sz[u2][0];
            int s1=sz[u1][1]-sz[u2][1];
            if(s0+s1>k){
                v|=1<<i;
                w1=u1,w2=u2;
            }else{
                k-=s0+s1;
                ss+=sum[u1]-sum[u2];
                c0+=s0,c1+=s1;
                w1=ch[w1][0],w2=ch[w2][0];
            }
        }
        if(c0&1){
            int l0,l1,r0,r1;
            _a=0,_x=v;
            _v=0,getpv(rt[r],rt[l-1],0,(1<<21)-1),l0=_v;
            _x=v+1;
            _v=0,getnx(rt[r],rt[l-1],0,(1<<21)-1),l1=_v;
            _a=1,_x=v;
            _v=0,getpv(rt[r],rt[l-1],0,(1<<21)-1),r0=_v;
            _x=v+1;
            _v=0,getnx(rt[r],rt[l-1],0,(1<<21)-1),r1=_v;
            int d1=r1&&l0?r1[id][xs]-l0[id][xs]:inf,d2=l1&&r0?l1[id][xs]-r0[id][xs]:inf;
            if(d1==inf&&d2==inf){
                puts("-1");
                return;
            }
            ss-=std::min(d1,d2);
        }
        printf("%lld
    ",ss);
    }
    bool cmp(int a,int b){
        return xs[a]<xs[b];
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin)[buf]=0;
        n=_();
        for(int i=1,x;i<=n;++i)xs[id[i]=i]=_();
        std::sort(id+1,id+n+1,cmp);
        for(int i=1,x;i<=n;++i)ir[id[i]]=i;
        for(int i=1;i<=n;++i){
            rt[i]=ins(rt[i-1],ir[i],xs[i]);
        }
        for(q=_();q;--q){
            int l=_(),r=_(),k=_();
            query(l,r,k);
        }
        return 0;
    }
  • 相关阅读:
    jQuery初学:find()方法及children方法的区别分析
    百万级访问网站前期的技术准备
    TCP/IP协议三次握手与四次握手流程解析
    TCP/IP详解学习笔记
    Dubbo框架入门介绍
    如何提高Web服务端并发效率的异步编程技术
    杂 -- 有关程序员
    关于高性能的那点事
    大型网站的灵魂- 性能
    分布式java应用
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6607180.html
Copyright © 2011-2022 走看看