赞
踩
牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ
题目描述
想必你一定会用线段树维护等差数列吧?让我们来看看它的升级版。
请你维护一个长度为5×10 ^5的数组,一开始数组中每个元素都为0,要求支持以下两个操作:
1、区间[l,r]加自然数的平方数组,即al+=1,al+1+=4,al+2+=9,al+3+=16...ar+=(r−l+1)∗(r−l+1)
2、区间[l,r]查询区间和mod 10^9 + 7
输入描述:
第一行输入n,m,(1≤n,m≤5*10 ^5)
接下来m行,对于每行,先读入一个整数q。
当q的值为1时,还需读入两个整l,r,(1≤l≤r≤n)表示需要对区间[l,r]进行操作,让第一个元素加1,第二个元素加4,第三个元素加9...以此类推。
当q的值为2时,还需读入两个整数l,r(1≤l≤r≤n)表示查询l到r的元素和
输出描述:
对于每一个q=2,输出一行一个非负整数,表示l到r的区间和mod 110^9+7。
示例1
输入
复制
4 4
2 1 4
1 1 4
1 3 4
2 1 4
输出
复制
0
35
示例2
输入
复制
10 6
1 1 6
1 8 9
1 3 6
2 1 10
1 1 10
2 1 10
输出
复制
126
511
等差数列可以写成 [x-(l-1)]^2,其中 x 表示当前的位置,等价于 x^2-2*x*(l-1)+(l-1)^2,通过线段树维护其系数即可
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <cmath>
- #include <ctime>
- #include <algorithm>
- #include <utility>
- #include <stack>
- #include <queue>
- #include <vector>
- #include <set>
- #include <math.h>
- #include <map>
- #include <sstream>
- #include <deque>
- #include <unordered_map>
- #include <unordered_set>
- #include <bitset>
- #include <stdio.h>
- #include <tuple>
- using namespace std;
- /*
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- */
- typedef long long LL;
- #define int long long
- #define ld long double
- //#define INT __int128
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- typedef unsigned long long ULL;
- typedef pair<long long, long long> PLL;
- typedef pair<int, int> PII;
- typedef pair<double, double> PDD;
- const int inf = 0x3f3f3f3f;
- const LL mod = 1e9+7;
- const ld eps = 1e-12;
- const int N = 5e5 + 10, M = N + 10;
- int n, m;
- struct TREE {
- int l, r;
- int la1, la2, la3;
- int sum;
- int base1, base2;
- }tr[N << 2];
- #define ls u<<1
- #define rs u<<1|1
- void cal(int u, int la1, int la2, int la3) {
- la3 %= mod;
- int len = tr[u].r - tr[u].l + 1;
- tr[u].sum = (tr[u].sum + len * la3 % mod) % mod;
- tr[u].sum = (tr[u].sum - 2 * tr[u].base2 * la2 % mod + mod) % mod;
- tr[u].sum = (tr[u].sum + tr[u].base1 * la1 % mod) % mod;
- tr[u].la1 = (tr[u].la1 + la1) % mod;
- tr[u].la2 = (tr[u].la2 + la2) % mod;
- tr[u].la3 = (tr[u].la3 + la3) % mod;
- }
- void up(int u) {
- tr[u].sum = (tr[ls].sum + tr[rs].sum) % mod;
- }
- void down(int u) {
- if (tr[u].la1||tr[u].la2||tr[u].la3) {
- cal(ls, tr[u].la1, tr[u].la2, tr[u].la3);
- cal(rs, tr[u].la1, tr[u].la2, tr[u].la3);
- tr[u].la1 = tr[u].la2 = tr[u].la3 = 0;
- }
- }
- void build(int u, int l, int r) {
- tr[u].l = l, tr[u].r = r;
- if (l == r) {
- tr[u].base1 = (l * l) % mod , tr[u].base2 = l;
- return;
- }
- int mid = (l + r) >> 1;
- build(ls, l, mid), build(rs, mid + 1, r);
- tr[u].base1 = (tr[ls].base1 + tr[rs].base1) % mod;
- tr[u].base2 = (tr[ls].base2 + tr[rs].base2) % mod;
- }
- void modify(int u, int l, int r, int d) {
- if (l <= tr[u].l && tr[u].r <= r) {
- cal(u, 1, d, d * d);
- return;
- }
- down(u);
- int mid = (tr[u].l + tr[u].r) >> 1;
- if (l <= mid)modify(ls, l, r, d);
- if (r > mid)modify(rs, l, r, d);
- up(u);
- }
- int query(int u, int l, int r) {
- if (l <= tr[u].l && tr[u].r <= r) {
- return tr[u].sum;
- }
- down(u);
- int ret = 0;
- int mid = (tr[u].l + tr[u].r) >> 1;
- if (l <= mid)ret = (ret + query(ls, l, r)) % mod;
- if (r > mid)ret = (ret + query(rs, l, r)) % mod;
- //up(u);
- return ret;
- }
- signed main() {
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- cin >> n >> m;
- build(1, 1, n);
- int op, l, r;
- while (m--) {
- cin >> op >> l >> r;
- if (op == 1) {
- modify(1, l, r, l - 1);
- }
- else {
- cout << query(1, l, r) << endl;
- }
- }
- return 0;
- }
- /*
- 4 5
- 2 1 4
- 1 1 4
- 2 1 4
- 1 3 4
- 2 1 4
- 4 5
- 2 1 4
- 1 3 4
- 2 1 4
- 1 1 4
- 2 1 4
- */
解析:
不能发现这个问题如果不带修改则可以用 dp+前缀和(矩阵乘法)解决,带修改则可以用线段树维护区间和。
令 f[i][0/1] 表示从第 1 层的左边(0)或右边(1)到第 i 层的左边(0)或右边(1)的方案数
我们可以将每一层的转移状态用矩阵表示,
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <cmath>
- #include <ctime>
- #include <algorithm>
- #include <utility>
- #include <stack>
- #include <queue>
- #include <vector>
- #include <set>
- #include <math.h>
- #include <map>
- #include <sstream>
- #include <deque>
- #include <unordered_map>
- #include <unordered_set>
- #include <bitset>
- #include <stdio.h>
- #include <tuple>
- using namespace std;
- /*
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- */
- typedef long long LL;
- //#define int long long
- #define ld long double
- //#define INT __int128
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- typedef unsigned long long ULL;
- typedef pair<long long, long long> PLL;
- typedef pair<int, int> PII;
- typedef pair<double, double> PDD;
- const int inf = 0x3f3f3f3f;
- const LL mod = 1e9 + 7;
- const ld eps = 1e-12;
- const int N = 2e5 + 10, M = N + 10;
- int n, m;
- char s[N];
- struct MATRIX {
- LL a[2][2];
- void init(int b1,int b2,int b3,int b4) {
- a[0][0] = b1, a[0][1] = b2;
- a[1][0] = b3, a[1][1] = b4;
- }
- MATRIX operator*(MATRIX oth) {
- MATRIX ret;
- ret.init(0, 0, 0, 0);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- for (int k = 0; k < 2; k++) {
- (ret.a[i][j] += a[i][k] * oth.a[k][j] % mod) %= mod;
- }
- }
- }
- return ret;
- }
- };
-
- struct TREE {
- int l, r;
- MATRIX ma;
- }tr[N << 2];
- #define ls u<<1
- #define rs u<<1|1
- void up(int u) {
- tr[u].ma = tr[ls].ma * tr[rs].ma;
- }
- void build(int u, int l, int r) {
- tr[u].l = l, tr[u].r = r;
- if (l == r) {
- tr[u].ma.init(1, s[l] == '/', s[l] != '/', 1);
- return;
- }
- int mid = l + r >> 1;
- build(ls, l, mid), build(rs, mid + 1, r);
- up(u);
- }
- void modify(int u, int pos, char ch) {
- if (tr[u].l == tr[u].r) {
- tr[u].ma.init(1, ch == '/', ch != '/', 1);
- return;
- }
- int mid = tr[u].l + tr[u].r >> 1;
- if (pos <= mid)modify(ls, pos, ch);
- if (pos > mid)modify(rs, pos, ch);
- up(u);
- }
- MATRIX query(int u, int l, int r) {
- if (l <= tr[u].l && tr[u].r <= r) {
- return tr[u].ma;
- }
- int mid = tr[u].l + tr[u].r >> 1;
- MATRIX ret;
- ret.init(1, 0, 0, 1);
- if (l <= mid)ret = (ret * query(ls, l, r));
- if (r > mid)ret = (ret * query(rs, l, r));
- return ret;
- }
- signed main() {
- cin >> n >> m;
- scanf("%s", s + 1);
- build(1, 1, n - 1);
- int op, ht, hs, h;
- for (int i = 1; i <= m; i++) {
- scanf("%d", &op);
- if (op == 0) {
- char c[2];
- scanf("%d%s",&h, c);
- modify(1, h,c[0]);
- }
- else {
- int ps, pt;
- scanf("%d%d%d%d",&hs,&ht, &ps, &pt);
- auto ret = query(1, hs, ht - 1);
- /*cout << "__________________" << endl;
- for (int i = 0; i < 2; i++) {
- cout << ret.a[i][0] << " " << ret.a[i][1] << endl;
- }
- cout << endl;*/
- LL ans = ret.a[ps][pt];
- printf("%lld\n", ans);
- }
- }
- return 0;
- }
这题思路与上题一样,只不过将矩阵的乘法运算换成 floyd 算法,矩阵的含义变为图的邻接矩阵。(可以变的主要原因是因为 floyd 算法的运算形式与矩阵连乘的形式很相似)
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <cmath>
- #include <ctime>
- #include <algorithm>
- #include <utility>
- #include <stack>
- #include <queue>
- #include <vector>
- #include <set>
- #include <math.h>
- #include <map>
- #include <sstream>
- #include <deque>
- #include <unordered_map>
- #include <unordered_set>
- #include <bitset>
- #include <stdio.h>
- #include <tuple>
- using namespace std;
- /*
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- */
- typedef long long LL;
- //#define int long long
- #define ld long double
- //#define INT __int128
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- typedef unsigned long long ULL;
- typedef pair<long long, long long> PLL;
- typedef pair<int, int> PII;
- typedef pair<double, double> PDD;
- const int inf = 0x3f3f3f3f;
- const LL mod = 1e9 + 7;
- const ld eps = 1e-12;
- const int N = 1e5 + 10, M = N + 10;
- int n, m;
- int val[N][3];
- char s[N];
- #define inf INF
- struct MATRIX {
- LL a[2][2];
- void init(LL b1, LL b2, LL b3, LL b4) {
- a[0][0] = b1, a[0][1] = b2;
- a[1][0] = b3, a[1][1] = b4;
- }
- MATRIX operator*(MATRIX oth) {
- MATRIX ret;
- ret.init(inf, inf, inf, inf);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 2; j++) {
- for (int k = 0; k < 2; k++) {
- //(ret.a[i][j] += a[i][k] * oth.a[k][j] % mod) %= mod;
- if (a[i][k] == inf || oth.a[k][j] == inf)continue;
- ret.a[i][j] = min(ret.a[i][j], (a[i][k] + oth.a[k][j]));
- }
- }
- }
- return ret;
- }
- };
-
- struct TREE {
- int l, r;
- MATRIX ma;
- }tr[N << 2];
- #define ls u<<1
- #define rs u<<1|1
- void up(int u) {
- tr[u].ma = tr[ls].ma * tr[rs].ma;
- }
- void build(int u, int l, int r) {
- tr[u].l = l, tr[u].r = r;
- if (l == r) {
- if (s[l] == '/')
- tr[u].ma.init(val[l][0], val[l][2], inf, val[l][1]);
- else tr[u].ma.init(val[l][0], inf, val[l][2], val[l][1]);
- return;
- }
- int mid = l + r >> 1;
- build(ls, l, mid), build(rs, mid + 1, r);
- up(u);
- }
- void modify(int u, int pos, char ch, int val1, int val2, int val3) {
- if (tr[u].l == tr[u].r) {
- if (ch == '/')
- tr[u].ma.init(val1, val3, inf, val2);
- else tr[u].ma.init(val1, inf, val3, val2);
- return;
- }
- int mid = tr[u].l + tr[u].r >> 1;
- if (pos <= mid)modify(ls, pos, ch, val1, val2, val3);
- if (pos > mid)modify(rs, pos, ch, val1, val2, val3);
- up(u);
- }
- MATRIX query(int u, int l, int r) {
- if (l <= tr[u].l && tr[u].r <= r) {
- return tr[u].ma;
- }
- int mid = tr[u].l + tr[u].r >> 1;
- MATRIX ret;
- ret.init(0, inf, inf, 0);
- if (l <= mid)ret = ret * query(ls, l, r);
- if (r > mid)ret = ret * query(rs, l, r);
- return ret;
- }
- signed main() {
- cin >> n >> m;
- scanf("%s", s + 1);
- for (int i = 1; i < n; i++) {
- scanf("%d%d%d", &val[i][0], &val[i][1], &val[i][2]);
- }
- build(1, 1, n - 1);
- int op, ht, hs, h;
- for (int i = 1; i <= m; i++) {
- scanf("%d", &op);
- if (op == 0) {
- char c[2];
- scanf("%d%s", &h, c);
- //cout << "______" << c[0] << endl;
- s[h] = c[0];
- modify(1, h, c[0], val[h][0], val[h][1], val[h][2]);
- }
- else if (op == 1) {
- int val1, val2, val3;
- scanf("%d%d%d%d", &h, &val1, &val2, &val3);
- val[h][0] = val1, val[h][1] = val2, val[h][2] = val3;
- modify(1, h, s[h], val1, val2, val3);
- }
- else {
- int ps, pt;
- scanf("%d%d%d%d", &hs, &ht, &ps, &pt);
- auto ret = query(1, hs, ht - 1);
- /*cout << "__________________" << endl;
- for (int i = 0; i < 2; i++) {
- cout << ret.a[i][0] << " " << ret.a[i][1] << endl;
- }
- cout << endl;*/
- LL ans = ret.a[ps][pt];
- if (ans == inf) {
- printf("-1\n");
- }
- else
- printf("%lld\n", ans);
- }
- }
- return 0;
- }
-
- /*
- 4 13
- ///
- 1 2 1
- 2 3 5
- 8 8 1
- 2 1 4 1 0
- 2 1 2 1 0
- 2 2 3 1 0
- 2 3 4 1 0
- 0 3 \
- 2 1 4 0 0
- 2 2 4 0 0
- 2 2 4 0 1
- 2 3 4 0 1
- 2 3 4 1 0
- 1 1 1 1 1
- 1 2 1 1 1
- 1 3 1 1 1
- 2 1 4 1 0
- 0 3 /
- 2 1 4 1 0
- 4 13
- ///
- 1 2 1
- 2 3 5
- 8 8 1
- 2 1 4 1 0
- 0 3 \
- 2 1 4 0 0
- 2 2 4 0 0
- 2 2 4 0 1
- 2 3 4 0 1
- 2 3 4 1 0
- 1 1 1 1 1
- 1 2 1 1 1
- 1 3 1 1 1
- 2 1 4 1 0
- 0 3 /
- 2 1 4 1 0
- */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。