Codeforces 295A. Greg and Array
Posted Ashly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 295A. Greg and Array相关的知识,希望对你有一定的参考价值。
题目链接:http://codeforces.com/problemset/problem/295/A
题意:
给你一个含有 n 个数的数组, 以及 m 个形如 ( l, r, v) 的操作,代表把这个数组从第 l 个到第 r 个全部加 v; 然后再给 k 个形如 ( l, r) 的操作,代表对于这 m 个操作, 分别执行第 a 个操作到第 b 个操作各一次.
思路:
这道题可以分解成两个同样的子问题,设原始数组为 a, 第一个操作为 b, 第二个操作为 c, 可以看到 b 是对于 a 数组从 l 到 r 加 v, 而 c 数组是对 b 的执行次数从 l 到 r 加 1. 这两个问题类似,对 b 设置一个属性 cnt 代表这个命令要执行多少次, 刚开始是不执行的所以初始化为 0 就好,设辅助数组 tp[i] =b[i].cnt - b[i - 1].cnt; 那么对数组 b 从第 l 到第 r 加 1 就相当于 tp[l]++, tp[r + 1]--; 最后再从 1 到 m 对数组 b 执行 b[i].cnt = b[i - 1].cnt + tp[i]. 这时就可以用 O(N)的复杂度得到对于操作 b, 其每个操作分别执行多少次.然后用同样的方法, 对数组 a 进行操作, 设辅助数组 tp[i] = a[i] - a[ i - 1], 则对与数组 a 从 l 到 r 加 v, 执行 cnt 次, 就相当与执行 tp[l] += cnt * v, tp[r + 1] -= cnt * v, 等所有操作完成后, 再次对于数组 a 进行恢复, 从 1 到 n, 对数组 a 执行 a[i] = a[i -1] + b[i].那么就可以在 O(n + m) 的时间复杂度里解决该问题.
代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 typedef long long LL; 5 6 const int MAXN = 100000; 7 8 struct Opera {LL l; LL r; LL v; LL cnt;}; //第一个操作, l r分别为左右区间 v 为所累加的 值, cnt 代表这个操作执行的次数 9 Opera opa[MAXN + 3]; 10 11 int main() { 12 ios_base::sync_with_stdio(0); cin.tie(0); 13 int n, m, k; cin >> n >> m >> k; 14 LL arv[MAXN + 3] = {0}; 15 for(int i = 1; i <= n; i++) cin >> arv[i]; 16 for(int i = 1; i <= m; i++) cin >> opa[i].l >> opa[i].r >> opa[i].v; 17 LL bop[MAXN + 3] = {0}; // bop[i] = opa[i].v - opa[i - 1].v, opa[].v 初始化为 0, 所以此数组不用初始化 18 for(int i = 0; i < k; i++) { 19 int l, r; cin >> l >> r; 20 bop[l]++, bop[r + 1]--;// 对数组opa[].v从 l 到 r 加 1, 就相当于 bop[l]++, bop[r + 1]--. 21 } 22 for(int i = 1; i <= m; i++) opa[i].cnt = opa[i - 1].cnt + bop[i]; //再倒过来恢复, 就可以得到每个操作的次数 23 LL ba[MAXN + 3] = {0}; // ba[i] = a[i] - a[i -1] 24 for(int i = 1; i <= n; i++) ba[i] = arv[i] - arv[i - 1];// a[] 每个值不确定, 需要对数组 ba 进行初始化 25 for(int i = 1; i <= m; i++) {// 对数组 a 从 opa[i].l 到 opa[i].r 加 v, 且执行 cnt 次的等价变换 26 ba[ opa[i].l ] += opa[i].v * opa[i].cnt; 27 ba[ opa[i].r + 1] -= opa[i].v * opa[i].cnt; 28 } 29 for(int i = 1; i <= n; i++) arv[i] = arv[i - 1] + ba[i]; // 再变化回来 30 for(int i = 1; i <= n; i++) cout << arv[i] << (i == n ? ‘\n‘: ‘ ‘); 31 return 0; 32 }
以上是关于Codeforces 295A. Greg and Array的主要内容,如果未能解决你的问题,请参考以下文章
295B - Greg and Graph (floyd逆序处理)
G - Greg and Array CodeForces - 296C 差分+线段树
codeforces 521a//DNA Alignment// Codeforces Round #295(Div. 1)