zoukankan      html  css  js  c++  java
  • uoj#29. 【IOI2014】Holiday

    http://uoj.ac/problem/29

    经过的点集一定是一个包含start的区间,为了经过这个区间内所有点,必须先到达一个区间端点,再到达另一个区间端点,剩余的步数则贪心选区间内最大价值的点。显然决策单调,于是可以分治,用可持久化线段树快速求出区间前k大数之和。

    #include"holiday.h"
    #include<cstring>
    #include<algorithm>
    typedef long long i64;
    const int N=500007;
    i64 ans=0;
    int v[N],*vs[N],S,D;
    struct node{
        node*c[2];
        int sz;
        i64 s;
    }ns[N*21],*np=ns,*rt[N];
    i64 kmx(int L,int R,int x){
        node*w1=rt[L],*w2=rt[R+1];
        i64 sum=0;
        for(int i=16;i>=0;--i){
            int s=w1->c[0]->sz-w2->c[0]->sz;
            if(s<=x){
                x-=s;
                sum+=w1->c[0]->s-w2->c[0]->s;
                w1=w1->c[1];
                w2=w2->c[1];
            }else{
                w1=w1->c[0];
                w2=w2->c[0];
            }
        }
        return sum;
    }
    node*ins(node*w,int x,int v){
        node*u=++np,*u0=u;
        for(int i=16;i>=0;--i){
            int d=x>>i&1;
            u->c[d^1]=w->c[d^1];
            u=u->c[d]=++np;w=w->c[d];
            u->sz=w->sz+1;
            u->s=w->s+v;
        }
        return u0;
    }
    void calc1(int L,int R,int l,int r){
        if(L>R)return;
        int M=L+R>>1,m=l,res=D-(S-M)*2-(l-S);
        i64 mv=-1;
        for(int i=l;i<=r&&res>=0;++i,--res){
            i64 v=kmx(M,i,res);
            if(v>mv)mv=v,m=i;
        }
        if(ans<mv)ans=mv;
        calc1(L,M-1,l,m);
        calc1(M+1,R,m,r);
    }
    void calc2(int L,int R,int l,int r){
        if(L>R)return;
        int M=L+R>>1,m=r,res=D-(M-S)*2-(S-r);
        i64 mv=-1;
        for(int i=r;i>=l&&res>=0;--i,--res){
            i64 v=kmx(i,M,res);
            if(v>mv)mv=v,m=i;
        }
        if(ans<mv)ans=mv;
        calc2(L,M-1,l,m);
        calc2(M+1,R,m,r);
    }
    bool cmp(int*a,int*b){
        return *a>*b;
    }
    i64 findMaxAttraction(int n,int start,int d,int attr[]){
        rt[n]=ns->c[0]=ns->c[1]=ns;
        memcpy(v,attr,sizeof(int)*n);
        for(int i=0;i<n;++i)vs[i]=v+i;
        std::sort(vs,vs+n,cmp);
        for(int i=0;i<n;++i)*vs[i]=i;
        for(int i=n-1;i>=0;--i)rt[i]=ins(rt[i+1],v[i],attr[i]);
        D=d;S=start;
        calc1(std::max(0,S-d/2),S,S,n-1);
        calc2(S,std::min(n-1,S+d/2),0,S);
        return ans;
    }
    #include"grader.cpp"
  • 相关阅读:
    PHP7革新与性能优化
    git团队开发
    PHP获取机器mac代码
    js复制文字
    jquery datatable客户端分页保持
    自已编写C# DLL 绑定到unity进程进行单步调试
    ‘xxfile' Missing the class attribute 'ExtensionOfNativeClass'
    关于热更的杂记
    关于unityengine.dll, unityengine.coremodule.dll
    学到了关于服务器磁盘阵列
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7504086.html
Copyright © 2011-2022 走看看