zoukankan      html  css  js  c++  java
  • 【CF115E】Linear Kingdom Races 题解(线段树优化DP)

    前言:前辈讲课时设的状态还是有些繁琐,感觉题解设的状态更简洁。

    --------------

    题目链接

    题目大意:给定$n$条道路和$m$场比赛,每个道路修建需要$c_i$,每场比赛需要使用$[l_i,r_i]$内的道路,收益为$p_i$。问最大收益。$n,mleq 200000$

    先将所有的区间右端点从小到大排序。

    设$f[i][j]$表示已经考虑前$i$条道路,最右边没有修的道路是$j$。现在考虑转移。

    如果不修第$i$条道路,那么最右边的没有修的道路就变成$i$了。有这样的方程$f[i][i]=max(f[i][i],f[i-1][j]) (0leq jleq i-1)$

    如果修第$i$条道路,那么以$i$为右端点的比赛都能获得收益。有$f[i][j]=f[i-1][j]+p(0leq jleq l_i-1)$。但是不要忘记修路的费用,即$f[i][j]=f[i-1][j]-cost[i](0leq jleq i-1)$。

    这样的转移是$O(n^2)$的,还不够优秀。注意到只需要维护区间最大值和序列和,我们可以用线段树来维护,只用维护懒标记,区间加和区间最大值这三个操作即可。

    至于以右端点进行关键字排序,可以开一个$vector$数组来存左端点和值。

    时间复杂度$O(nlog n)$。

    代码:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int n,m;
    struct Node
    {
        int first,second;
    };
    vector<Node> a[200005];
    struct node
    {
        int lazy,a,max;
    }tree[1000005];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void pushdown(int index)
    {
        tree[index*2].lazy+=tree[index].lazy;
        tree[index*2+1].lazy+=tree[index].lazy;
        tree[index*2].max+=tree[index].lazy;
        tree[index*2+1].max+=tree[index].lazy;
        tree[index].lazy=0;
    }
    inline void update(int index,int l,int r,int ql,int qr,int x)
    {
        if (ql<=l&&r<=qr) {tree[index].lazy+=x;tree[index].max+=x;return;}
        if (tree[index].lazy) pushdown(index);
        int mid=(l+r)/2;
        if (ql<=mid) update(index*2,l,mid,ql,qr,x);
        if (qr>mid) update(index*2+1,mid+1,r,ql,qr,x);
        tree[index].max=max(tree[index*2].max,tree[index*2+1].max);
    }
    inline int query(int index,int l,int r,int ql,int qr)
    {
        if (ql<=l&&r<=qr) return tree[index].max;
        if (tree[index].lazy) pushdown(index);
        int mid=(l+r)/2,res=0;
        if (ql<=mid) res=max(res,query(index*2,l,mid,ql,qr));
        if (qr>mid) res=max(res,query(index*2+1,mid+1,r,ql,qr));
        return res; 
    }
    signed main()
    {
        n=read(),m=read();
        for (int i=1;i<=n;i++) tree[i].a=read();
        for (int i=1;i<=m;i++) 
        {
            int l=read(),r=read(),x=read();
            a[r].push_back((Node){l,x});
        }
        for (int i=1;i<=n;i++)
        {
            //f[i][i]=max(f[i][i],f[i-1][j])
            update(1,0,n,i,i,query(1,0,n,0,i-1));
            //f[i][j]=f[i-1][j]+p-cost;
            for (int j=0;j<a[i].size();j++) update(1,0,n,0,a[i][j].first-1,a[i][j].second);
            update(1,0,n,0,i-1,-tree[i].a);
        }
        printf("%lld",tree[1].max);
        return 0;
    }
  • 相关阅读:
    linux 下 mysql 常用命令
    极光推送-服务端代码
    spring定时任务表达式
    结合 Redis 实现同步锁
    MySQL 常用函数
    PostgreSQL查询优化逻辑优化之其他
    PostgreSQL查询优化之子查询优化
    PostgreSQL查询优化器之grouping_planner
    PostgreSQL事务实现
    zookeeper ZAB协议 Follower和leader源码分析
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13301431.html
Copyright © 2011-2022 走看看