• dtoj#4212. 小X爱旅行(travel)


    题目描述:

    OIVillage 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,xkszltl 决定修建了一条铁路将当地 $n$ 个最著名的经典连接起来,让游客可以通过火车从铁路起点( $1$ 号景点)出发,依次游览每个景区。为了更好的评价这条铁路,xkszltl 为每一个景区都赋予了一个美观度,而一条旅行路径的价值就是它所经过的景区的美观度之和。不过,随着天气与季节的变化,某些景点的美观度也会发生变化。

    xkszltl 希望为每位旅客提供最佳的旅行指导,但是由于游客的时间有限,不一定能游览全部景区,然而他们也不希望旅途过于短暂,所以每个游客都希望能在某一个区间内的车站结束旅程,而 xkszltl 的任务就是为他们选择一个终点使得旅行线路的价值最大。可是当地的景点与前来观光的旅客实在是太多了,xkszltl 无法及时完成任务,于是找到了准备虐杀 NOI2019 的你,希望你能帮助他完成这个艰巨的任务。

    输入:

    第一行给出一个整数 $n$,接下来一行给出 $n$ 的景区的初始美观度。

    第三行给出一个整数 $m$,接下来 $m$ 行每行为一条指令:

    $1.~~~0~x~y~k$:表示将 $x$ 到 $y$ 这段铁路边上的景区的美观度加上 $k$;

    $2.~~~1~x~y$:表示有一名旅客想要在 $x$ 到 $y$ 这段(含 $x$ 与 $y$ )中的某一站下车,你需要告诉他最大的旅行价值。

    数据范围:

    对于 $20\%$ 的数据,$n,m≤3000$;

    对于 $40\%$ 的数据,$n,m≤30000$;

    对于 $50\%$ 的数据,$n,m≤50000$;

    另外 $20\%$ 的数据,$n,m≤100000$,修改操作 $≤20$;

    对于 $100\%$ 的数据,$n,m≤100000$。

    算法标签:分块,凸包

    思路:

    考虑分块计算,对于每一个块做一个凸包,对于单词修改或询问如果遍布整个块,就对这个块记录一个 $k,b$ 表示整个块的数都要进行的操作。

    因为是一次函数所以更改后最优答案一定在凸包上。

    对于只修改或查询一个块内一部分点的情况,暴力操作。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define db double
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e5+5,M=1505;
    const LL inf=1e18;
    vector<int> v[M];
    int n,m,sz,gr[N],sta[N],top;
    LL sum[N],k[N],b[N];
    il int read(){
        int x,f=1;char ch;
        _(!)ch=='-'?f=-1:f;x=ch^48;
        _()x=(x<<1)+(x<<3)+(ch^48);
        return f*x;
    }
    il db getk(int x,int y){
        return (db)(sum[x]-sum[y])/(db)(x-y);
    }
    il void build(int x){
        int l=(x-1)*sz+1,r=min(x*sz,n);
        sta[top=1]=l;
        for(int i=l+1;i<=r;i++){
            while(top>1&&getk(sta[top],sta[top-1])<getk(sta[top-1],i))top--;
            sta[++top]=i;
        }
        v[x].resize(top+1);
        for(int i=1;i<=top;i++)v[x][i]=sta[i];
    }
    il LL cal(int x){
        return sum[x]+k[gr[x]]*x+b[gr[x]];
    }
    il LL query(int x){
        int l=1,r=v[x].size()-1;
        if(l>r)return cal(v[x][1]);
        while(l<r){
            int mid=(l+r)>>1;
            if(cal(v[x][mid])<cal(v[x][mid+1]))l=mid+1;
            else r=mid;
        }
        return cal(v[x][l]);
    }
    il void update(int x){
        int l=(x-1)*sz+1,r=min(x*sz,n);
        LL v=k[x]*l+b[x];
        for(int i=l;i<=r;i++)sum[i]+=v,v+=k[x];
        k[x]=b[x]=0;
    }
    int main()
    {
        n=read();sz=sqrt(n/3);
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+read();
        for(int i=1;i<=n;i++)gr[i]=(i-1)/sz+1;
        for(int i=1;i<=gr[n];i++)build(i);
        m=read();
        while(m--){
            int op=read(),x=read(),y=read();
            if(op){
                LL ans=-inf;
                if(gr[x]^gr[y]){
                    for(int i=x;i<=gr[x]*sz;i++)ans=max(ans,cal(i));
                    for(int i=(gr[y]-1)*sz+1;i<=y;i++)ans=max(ans,cal(i));
                    for(int i=gr[x]+1;i<gr[y];i++)ans=max(ans,query(i));
                }
                else{
                    for(int i=x;i<=y;i++)ans=max(ans,cal(i));
                }
                printf("%lld
    ",ans);
            }
            else{
                int c=read();
                if(gr[x]^gr[y]){
                    LL val=0;
                    for(int i=x;i<=gr[x]*sz;i++)val+=c,sum[i]+=val;
                    val=1ll*((gr[y]-1)*sz-x+1)*c;
                    for(int i=(gr[y]-1)*sz+1;i<=y;i++)val+=c,sum[i]+=val;
                    for(int i=y+1;i<=min(gr[y]*sz,n);i++)sum[i]+=val;
                    for(int i=gr[y]+1;i<=gr[n];i++)b[i]+=val;
                    update(gr[x]);update(gr[y]);build(gr[x]);build(gr[y]);
                    val=-1ll*c*(x-1);
                    for(int i=gr[x]+1;i<gr[y];i++)k[i]+=c,b[i]+=val;
                }
                else{
                    LL val=0;
                    for(int i=x;i<=y;i++)val+=c,sum[i]+=val;
                    for(int i=y+1;i<=min(gr[y]*sz,n);i++)sum[i]+=val;
                    for(int i=gr[y]+1;i<=gr[n];i++)b[i]+=val;
                    update(gr[x]);build(gr[x]);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    tomcat的HTTPS
    java websocket开发的客户端程序
    Java后端WebSocket的Tomcat实现
    java 注解
    工作队列
    中断共享(硬件角度)
    电平触发与边沿触发中断的理解
    kuser_cmpxchg_check 原子操作
    新建普通进程
    fork 至 “sys_clone" SyS_clone
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10443119.html
Copyright © 2020-2023  润新知