首页 > 其他分享 >[题解]AT_dp_w Intervals

[题解]AT_dp_w Intervals

时间:2024-06-23 13:13:51浏览次数:12  
标签:rs int 题解 read Intervals Theta dp define

思路

首先考虑较为普通的 DP。

定义 \(dp_{i,j}\) 表示在前 \(i\) 个位置中,最后一个 1 在 \(j\) 的最大分数,显然有:

\[ dp_{i,j} = \left\{\begin{matrix} \max_{k = 1}^{i - 1}\{dp_{i - 1,k}\} + \sum_{l_k \leq j \wedge r_k = i}{a_k} & (i = j)\\ dp_{i - 1,j} + \sum_{l_k \leq j \wedge r_k = i}{a_k} & (i \neq j) \end{matrix}\right. \]

发现这个状态是 \(\Theta(n^2)\) 的,但是可以滚掉一维,空间复杂度 \(\Theta(n)\),时间复杂度 \(\Theta(n^2)\)。

不难发现,对于每一个 \((l,r,a)\) 的三元组,会在 \(i = r\) 时,在 \(dp_{l \sim i}\) 中做出贡献,于是转变为了区间加。

然后对于第一个式子中的 \(\max\) 也就是区间查询最值。于是用线段树维护 \(dp\) 数组即可。

Code

#include <bits/stdc++.h>  
#define fst first  
#define snd second  
#define re register  
#define int long long  
  
using namespace std;  
  
typedef pair<int,int> pii;  
const int N = 2e5 + 10;  
int n,m;  
vector<pii> v[N];  
  
inline int read(){  
    int r = 0,w = 1;  
    char c = getchar();  
    while (c < '0' || c > '9'){  
        if (c == '-') w = -1;  
        c = getchar();  
    }  
    while (c >= '0' && c <= '9'){  
        r = (r << 3) + (r << 1) + (c ^ 48);  
        c = getchar();  
    }  
    return r * w;  
}  
  
struct seg{  
    #define ls(u) (u << 1)  
    #define rs(u) (u << 1 | 1)  
  
    struct node{  
        int l,r;  
        int Max,tag;  
    }tr[N << 2];  
  
    inline void calc(int u,int k){  
        tr[u].Max += k;  
        tr[u].tag += k;  
    }  
  
    inline void pushup(int u){  
        tr[u].Max = max(tr[ls(u)].Max,tr[rs(u)].Max);  
    }  
  
    inline void pushdown(int u){  
        if (tr[u].tag){  
            calc(ls(u),tr[u].tag);  
            calc(rs(u),tr[u].tag);  
            tr[u].tag = 0;  
        }  
    }  
  
    inline void build(int u,int l,int r){  
        tr[u] = {l,r};  
        if (l == r) return;  
        int mid = l + r >> 1;  
        build(ls(u),l,mid);  
        build(rs(u),mid + 1,r);  
    }  
  
    inline void modify(int u,int l,int r,int k){  
        if (l <= tr[u].l && tr[u].r <= r){  
            calc(u,k);  
            return;  
        }  
        pushdown(u);  
        int mid = tr[u].l + tr[u].r >> 1;  
        if (l <= mid) modify(ls(u),l,r,k);  
        if (r > mid) modify(rs(u),l,r,k);  
        pushup(u);  
    }  
  
    #undef ls  
    #undef rs  
}T;  
  
signed main(){  
    n = read();  
    m = read();  
    for (re int i = 1;i <= m;i++){  
        int l,r,w;  
        l = read();  
        r = read();  
        w = read();  
        v[r].push_back({l,w});  
    }  
    T.build(1,1,n);  
    for (re int i = 1;i <= n;i++){  
        T.modify(1,i,i,max(0ll,T.tr[1].Max));  
        for (auto p:v[i]) T.modify(1,p.fst,i,p.snd);  
    }  
    printf("%lld",max(0ll,T.tr[1].Max));  
    return 0;  
}  

标签:rs,int,题解,read,Intervals,Theta,dp,define
From: https://www.cnblogs.com/WaterSun/p/18263296

相关文章

  • [题解]AT_arc138_a [ARC138A] Larger Score
    思路不难发现:对于每一个\(i(1\leqi\leqk)\),如果能在\((k+1)\simn\)中找到任何一个\(j\),满足\(a_j>a_i\)就算满足条件。进一步思考,为了使操作数最小,对于每一个\(1(1\leqi\leqk)\),都找一个在\((k+1)\simn\)中第一个大于\(a_i\)的数,便于它交换。那么......
  • [题解]AT_arc116_d [ARC116D] I Wanna Win The Game
    思路因为题目与二进制有关,考虑往二进制的方向思考。定义\(dp_{i,j}\)表示在所有的\(n\)个数中,当前在决策对于每一个数在二进制表示下的第\(i\)位是\(0\)还是\(1\),且和为\(j\)的方案数。因为异或需要满足对于所有\(a_i\)表示为二进制后每一位\(1\)的个数均为偶数......
  • [题解]AT_arc116_b [ARC116B] Products of Min-Max
    思路我们容易可以得到一个朴素的做法,首先对\(a\)数组排序,然后枚举最大值和最小值\(a_i,a_j\),那么对于中间的元素都有选与不选两种情况,得到答案:\[\sum_{i=1}^{n}(a_i\timesa_i+(\sum_{j=i+1}^{n}a_i\timesa_j\times2^{j-i-1}))\]然后对这个式子......
  • [题解]AT_arc113_c [ARC113C] String Invasion
    题意给定一个字符串\(S\),你可以选择一个\(i(1\leqi\leq|S|)\),如果\(s_i=s_{i+1}\neqs_{i+2}\),就将\(s_{i+2}\)设为\(s_i\)。问:最多能操作几次。思路我们可以用一个后缀和\(s_{i,j}\)维护\(S_i\simS_n\)中与\(j\)不同的数量。然后,我们可以发现一......
  • [题解]AT_arc079_c [ARC079E] Decrease (Judge ver
    思路首先,对于每一次操作,我们可以先找到最大值,然后对其操作。这样,我们可以得到单次操作时间复杂度\(\Theta(n)\)的代码,因为\(n\)很小,所以这道题时间复杂度的瓶颈在于操作的数量。那么,我们想到每一次找到最大值时,直接将其减到小于\(n\)。但是这样可能有一种问题,就是最大值......
  • [题解]AT_agc054_b [AGC054B] Greedy Division
    思路首先不难发现一个规律,当\(sum\)为奇数时不可能有解。定义\(dp_{i,j,k,0/1}\)表示A在前\(i\)个数中选出和为\(j\)的\(k\)个数,且第\(i\)个不选/选的方案数。那么,我们只需要对于第\(i\)个数的状态分类讨论就能得到状态转移方程:不选\(i\),\(dp_{i,j,k,0}=......
  • [题解]AT_abc350_g [ABC350G] Mediator
    思路有加边操作,一眼LCT。问题在于处理询问操作。首先,判断联通。如果\(x,y\)不在同一个联通块内,则一定没有答案。其次,求出\(x,y\)之间节点的数量\(num\)(包括\(x,y\))。如果\(num=3\)说明\(x,y\)之间有一个共同的节点;如果\(num=2\)说明\(x,y\)直接连接;如果\(n......
  • [题解]AT_abc343_g [ABC343G] Compress Strings
    思路首先假设有两个串\(a,b\),如果\(b\)是\(a\)的子串,且\(a\neqb\)则不需要考虑\(b\);如果\(a=b\),则如需要保留一个\(a\)。做完上述操作后,显然最终的答案是由这些串按照一定顺序拼接起来,再删掉重叠部分。例如:abbcc与ccdde拼接为abbccccdde,发现cc是重复的,所以......
  • [题解]AT_abc342_f [ABC342F] Black Jack
    思路发现自己与庄家的操作是完全独立的,所以考虑分别计算它们。首先考虑自己的情况,定义\(dp_i\)表示掷出骰子的和为\(i\)获胜的概率,并记\(f(i)\)表示\(x=i\)时就不掷的获胜概率。对于每一步我们要么掷骰子(并且掷出的值等概率的在\(1\simD\)中),要么直接结束。两种情......
  • [题解]CF855E Salazar Slytherin's Locket
    思路毒瘤数位DP题。首先,你可以用一个vector储存每一个数字出现的次数,然后用map记忆化。然后可以得到如下TLE#8的代码。因为map自带一只\(\log\)所以,考虑将map优化掉。但是,现在每一种数字可能会出现很多次,所以要用vector维护出现次数,但这样必定需要用map一......