线段树 (ICPC小米预赛第二场 C Data Structure Problem)

Posted Kalzn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树 (ICPC小米预赛第二场 C Data Structure Problem)相关的知识,希望对你有一定的参考价值。

题目链接
题意:给你一个两个序列 b b b a a a,序列 c c c由其生成,生成方式为: c 0 = 0 , c i = m a x c i − 1 + b i , a i c_0=0,c_i=max\\c_i-1+b_i,a_i\\ c0=0,ci=maxci1+bi,ai
每次会对a、b进行单点修改,对c进行单点询问。
题解:首先如果不考虑a序列的影响。那么 c i = ∑ j = 1 i b i c_i=\\sum_j=1^ib_i ci=j=1ibi此时我们考虑因为有些位置, a i > b i a_i>b_i ai>bi所以,我们必须将答案在累计到“最高”的 a i a_i ai,即最后有以下公式:
c i = ∑ j = 1 i b j + m a x 0 , m a x 1 ≤ j ≤ i a j − ∑ k = 1 j b k c_i=\\sum_j=1^ib_j+max\\0,max_1\\le j\\le i\\a_j-\\sum_k=1^jb_k\\\\ ci=j=1ibj+max0,max1jiajk=1jbk
线段树很容易就可以维护 b b b a − b a-b ab序列的值。我们每查询 c i c_i ci,首先查询 b b b的前缀和,然后在查询 [ 1 , i ] [1,i] [1,i]区间中 a j − b j a_j-b_j ajbj的最大值,如果这个最大值小于0,答案即为 b b b的前缀和,否则答案即为 b b b的前缀和+这个最大值。(比赛的时候多亏了队友提了一嘴差值的事,QAQ。
下面是ac代码:

// % everyone
#include <cstdio>
#include<iostream>
#include<cstring>
#include <map>
#include <queue>
#include <set>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <cctype>
#include <time.h>

namespace IO 
    double start_time = 0.0;
    void ct()  start_time = clock(); return; 
    void fast_cin()  std::ios::sync_with_stdio(false); std::cin.tie(); 
    void read_f(int flag = 0)  freopen("0.in", "r", stdin); if(!flag) freopen("0.out", "w", stdout); 
    void run_time()  std::cout << "\\nESC in : " << ( clock() - start_time ) * 1000.0 / CLOCKS_PER_SEC << "ms" << std::endl; 

using namespace IO;
template <typename T>
bool bacmp(const T & a, const T & b)  return a > b; 
template <typename T>
bool pecmp(const T & a, const T & b)  return a < b; 

#define ll long long
#define ull unsigned ll
#define _min(x, y) ((x)>(y)?(y):(x))
#define _max(x, y) ((x)>(y)?(x):(y))
#define max3(x, y, z) ( max( (x), max( (y), (z) ) ) )
#define min3(x, y, z) ( min( (x), min( (y), (z) ) ) )
#define pr make_pair
#define pb push_back
#define int ll
using namespace std;

const int N = 2e5+6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
ll a[N], b[N], b0[N];
struct Node

    int l, r;
    ll a, b, dif;
    ll laz;
tr[N<<2];
void update(int p, int v)

    tr[p].laz += v;
    tr[p].b += v;
    tr[p].dif -= v;

void spread(int p)

    if (tr[p].laz == 0) return;
    update(p<<1, tr[p].laz);
    update(p<<1|1, tr[p].laz);
    tr[p].laz = 0;

void pushup(int p)

    tr[p].dif = max(tr[p<<1].dif, tr[p<<1|1].dif);

void build(int p, int l, int r)

    tr[p].l = l; tr[p].r = r;
    tr[p].laz = 0;
    if (l == r)
    
        tr[p].a = a[l];
        tr[p].b = b[l];
        tr[p].dif = a[l] - b[l];
        return;
    
    int mid = (l + r) >> 1;
    build(p<<1, l, mid);
    build(p<<1|1, mid+1, r);
    pushup(p);

void changeb(int p, int l, int r, int v)

    if (l <= tr[p].l && tr[p].r <= r)
    
        update(p, v); return;
    
    spread(p);
    int mid = (tr[p].l + tr[p].r) >> 1;
    if (l <= mid) changeb(p<<1, l, r, v);
    if (r > mid) changeb(p<<1|1, l, r, v);
    pushup(p);

void changea(int p, int pos, int v)

    if (tr[p].l == tr[p].r)
    
        tr[p].a += v;
        tr[p].dif += v;
        return;
    
    spread(p);
    int mid = (tr[p].l + tr[p].r) >> 1;
    if (pos <= mid) changea(p<<1, pos, v);
    else changea(p<<1|1, pos, v);
    pushup(p);

ll askb(int p, int x)

    if (tr[p].l == tr[p].r)
        return tr[p].b;
    int mid = (tr[p].l + tr[p].r) >> 1;
    spread(p);
    if (x <= mid) return askb(p<<1, x);
    else return askb(p<<1|1, x);

ll askdif(int p, int l, int r)

    if (l <= tr[p].l && tr[p].r <= r)
        return tr[p].dif;
    int mid = (tr[p].l + tr[p].r) >> 1;
    spread(p);
    ll val = -1ll * inf * inf;
    if (l <= mid) val = askdif(p<<1, l, r);
    if (r > mid) val = max(val, askdif(p<<1|1, l, r));
    return val;


signed main()

    int n, m;
    while(~scanf("%lld%lld", &n, &m))
    
        for (int i = 1; i <= n; i++)
            scanf("%lld", &a[i]);
        for (int i = 1; i <= n; i++)
            scanf("%lld", &b[i]), b0[i] = b[i], b[i] +=b[i-1];
        build(1, 1, n);
        while(m--)
        
            int op, x, y;
            scanf("%lld%lld", &op, &x);
            if (op == 3)
            
                ll g = askb(1, x);
                ll dif = max(0ll, askdif(1, 1, x));
                printf("%lld\\n", g+dif);
            
            else if (op == 1)
            
                scanfICPC网络赛第二场 L.Euler Function 欧拉函数性质+势能线段树

ICPC网络赛第二场 L.Euler Function 欧拉函数性质+势能线段树

ACM-ICPC 2018 南京赛区网络预赛 Lpl and Energy-saving Lamps 线段树

ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(线段树)

[计蒜客] ACM-ICPC 2018 南京赛区网络预赛 | 部分题解 | 线段树 + 线性筛 + 最短路

ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study (线段树)