uoj#29. IOI2014Holiday

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uoj#29. IOI2014Holiday相关的知识,希望对你有一定的参考价值。

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"

 

以上是关于uoj#29. IOI2014Holiday的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4367[IOI2014]holiday假期 分治+主席树

UOJ_407_IOI2018狼人

UOJ 407(IOI2018 D1T3)

UOJ 405(IOI2018 D1T1)

NOI2014BZOJ3669UOJ#3魔法森林

Luogu4899 IOI2018 Werewolf 主席树Kruskal重构树