[cf 1136] E. Nastya Hasn't Written a Legend

题意

给两个数组分别为\(a\)和\(k\),有若干次操作:

1.给\(a_x\)加上\(y\),并以此对\(a_{x + i}(i \ge 1)\)赋值为\(\max \{a_{x + i}, a_{x + i - 1} + k_{x + i - 1}\}\)。

2.询问区间\([l, r]\)的\(a_i\)的和。

题解

自闭了啊。

考虑把原序列分成若干个块,对于每个块内必须满足,除最后一个位置的所有位置\(i\),\(a_i + k_i = a_i + 1\)。刚开始可以看成有\(n\)个块。

每次修改的时候,直接对每个块内用线段树修改,块与块之间可能有合并(最多合并\(O(n + q)\)次),然后每一次修改可能会产生\(O(1)\)个新的块。所有块用一个set维护一下。所以总复杂度是\(O((n + q) \log n)\)的。

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;

inline int read () {
    static int x;
    scanf("%d", &x);
    return x;
}
const int N = 1e5 + 5, inf = 2e9;
int n, q, a[N], k[N]; ll pres[N];
set <pii> block;
ll s[N << 2], tag[N << 2];
#define mid ((l + r) >> 1)
#define lc (o << 1)
#define rc (o << 1 | 1)
#define ls lc, l, mid
#define rs rc, mid + 1, r
inline void pushdown (int o, int l, int r) {
    s[lc] += tag[o] * (mid - l + 1), tag[lc] += tag[o];
    s[rc] += tag[o] * (r - mid), tag[rc] += tag[o];
    tag[o] = 0;
}
inline void build (int o, int l, int r) {
    if (l == r) {s[o] = a[l]; return;}
    build(ls), build(rs);
    s[o] = s[lc] + s[rc];
}
inline void modify (int o, int l, int r, int x, int y, ll v) {
    if (x <= l && r <= y) {s[o] += v * (r - l + 1), tag[o] += v; return;}
    if (tag[o]) pushdown(o, l, r);
    if (x <= mid) modify(ls, x, y, v);
    if (y > mid) modify(rs, x, y, v);
    s[o] = s[lc] + s[rc];
}
inline ll query (int o, int l, int r, int x, int y) {
    if (x <= l && r <= y) return s[o];
    if (tag[o]) pushdown(o, l, r);
    ll ret = 0;
    if (x <= mid) ret += query(ls, x, y);
    if (y > mid) ret += query(rs, x, y);
    return ret;
}

void alter (int x, int v) {
    set <pii> :: iterator b; int l, r;
    b = block.lower_bound(mp(x, inf)), --b;
    l = b->fi, r = b->se;
    block.erase(b);
    if (l < x) block.insert(mp(l, x - 1));
    modify(1, 1, n, x, r, v);
    for ( ; r < n; ) {
        ll s = query(1, 1, n, r, r), t = query(1, 1, n, r + 1, r + 1), delta = s + k[r] - t;
        if (delta < 0) break;
        b = block.lower_bound(mp(r + 1, r + 1));
        l = b->fi, r = b->se;
        block.erase(b);
        modify(1, 1, n, l, r, delta);
    }
    block.insert(mp(x, r));
}
int main() {
    n = read();
    for (int i = 1; i <= n; ++i)
        a[i] = read(), pres[i] = pres[i - 1] + a[i];
    for (int i = 1; i < n; ++i) k[i] = read();
    for (int i = 1; i <= n; ++i) block.insert(mp(i, i));
    build(1, 1, n);
    char op[5]; int x, y;
    for (int _ = read(); _; --_) {
        scanf("%s", op), x = read(), y = read();
        if (op[0] == '+') alter(x, y); else
        printf("%lld\n", query(1, 1, n, x, y));
    }
    return 0;
}

[cf 1136] E. Nastya Hasn't Written a Legend

原文地址:https://www.cnblogs.com/psimonw/p/10727393.html

时间: 2024-10-31 18:18:42

[cf 1136] E. Nastya Hasn't Written a Legend的相关文章

Codeforces 1136E Nastya Hasn&#39;t Written a Legend (线段树教做人系列)

题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后,a[i + 1]<a[i] + k[i],那么a[i + 1]就变成a[i] + k[i],否则不变.同理,若a[i + 2]小于了现在的a[i + 1] + k[i + 1],那么a[i + 2]也变成a[i + 1] + k[i + 1],一直保持这个性质.第二章操作,询问数组a的区间[l, r]的

CF1136E Nastya Hasn&#39;t Written a Legend(线段树)

还能说什么呢,简直太妙了. $$a_{i+1}<a_i+k_i$$ $$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i+k_i-k_i-k_{i-1}-\cdots-k_1$$ $$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i-k_{i-1}-\cdots-k_1$$ 令 $k$ 的前缀和为 $kpre$. $$a_{i+1}-kpre_i<a_i-kpre_{i-1}$$ 令 $b_i=a_i-kpre_{i-1}$. $$b_{i+

Nastya Hasn&#39;t Written a Legend(Codeforces Round #546 (Div. 2)E+线段树)

题目链接 传送门 题面 题意 给你一个\(a\)数组和一个\(k\)数组,进行\(q\)次操作,操作分为两种: 将\(a_i\)增加\(x\),此时如果\(a_{i+1}<a_i+k_i\),那么就将\(a_{i+1}\)变成\(a_i+k_i\),如果\(a_{i+2}<a_i+k_i\),则将\(a_{i+2}\)变成\(a_{i+1}+k_{i+1}\),以此类推. 查询\(\sum\limits_{i=l}^{r}a_i\). 思路 我们首先存下\(k\)数组的前缀和\(sum1\),

codeforces 1136E-Nastya Hasn&#39;t Written a Legend

传送门:QAQQAQ 题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后,a[i + 1]<a[i] + k[i],那么a[i + 1]就变成a[i] + k[i],否则不变.同理,若a[i + 2]小于了现在的a[i + 1] + k[i + 1],那么a[i + 2]也变成a[i + 1] + k[i + 1],一直保持这个性质.第二章操作,询问数组

Codeforces 1136 - A/B/C/D/E/F - (Undone)

链接:https://codeforces.com/contest/1136/ A - Nastya Is Reading a Book - [二分] #include<bits/stdc++.h> using namespace std; const int maxn=105; int n,l[maxn],r[maxn],k; int srch(int x) { int L=1, R=n; while(L<R) { int M=(L+R)>>1; if(l[M]<=x

CF memsql Start[c]UP 2.0 A

CF memsql Start[c]UP 2.0 A A. Golden System time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Piegirl got bored with binary, decimal and other integer based counting systems. Recently she dis

CF 17B Hierarchy

Nick's company employed n people. Now Nick needs to build a tree hierarchy of ?supervisor-surbodinate? relations in the company (this is to say that each employee, except one, has exactly one supervisor). There are m applications written in the follo

【打CF,学算法——二星级】CodeForces 237B Young Table (构造)

[CF简介] 提交链接:CF 237B 题面: B. Young Table time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You've got table a, consisting of n rows, numbered from 1 to n. The i-th line of table a contains ci

pat 1136 A Delayed Palindrome(20 分)

1136 A Delayed Palindrome(20 分) Consider a positive integer N written in standard notation with k+1 digits a?i?? as a?k???a?1??a?0?? with 0≤a?i??<10 for all i and a?k??>0. Then N is palindromic if and only if a?i??=a?k?i?? for all i. Zero is written