题目背景
小新经常陪小白去公园玩,也就是所谓的遛狗啦…
题目描述
在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第aa个和第bb个公园之间(包括aa、bb两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
输入格式
第一行,两个整数NN和MM,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来NN行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来MM行,每行三个整数。第一个整数KK,11或22。
- K=1K=1表示,小新要带小白出去玩,接下来的两个整数aa和bb给出了选择公园的范围(1≤a,b≤N1≤a,b≤N)。测试数据可能会出现a>ba>b的情况,需要进行交换;
- K=2K=2表示,小白改变了对某个公园的打分,接下来的两个整数pp和ss,表示小白对第pp个公园的打分变成了ss(1≤p≤N1≤p≤N)。
其中,1≤N≤500 0001≤N≤500000,1≤M≤100 0001≤M≤100000,所有打分都是绝对值不超过10001000的整数。
输出格式
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
输入输出样例
输入 #1
5 3 1 2 -3 4 5 1 2 3 2 2 -1 1 2 3
输出 #1
2
-1思路:不得不说这个题是一个好题,而且加深了我对线段树的理解,让我知道了线段树还能这么用。其实这个题没想象中的难,个人感觉蓝题左右,难度不到紫题,洛谷评分虚高了一点。我这里用了一个技巧,用L表示区间左端点严格为线段树节点区间左端点的子序列最大值,R同理s则是区间左右端点不加以限制的最大值(也就是题目要的答案)。显然线段树在合并信息的时候,L的值为:max{左子节点的L,左子节点sum加上右子节点的L},R同理,s则为max{左子节点s,右子节点s,左子节点R与右子节点L的和}(想想为什么),然后按正常的线段树操作做即可。没想象中的难。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 const int N = 5e5 + 5;
7 struct seg{
8 int l, r;
9 int sum, L, R, s;
10 }tr[N << 2];
11 int n, m, num[N];
12 #define ls p << 1
13 #define rs p << 1|1
14 #define inf 2e9
15 void update(int p)
16 {
17 tr[p].sum = tr[ls].sum + tr[rs].sum;
18 tr[p].L = max(tr[ls].L, tr[ls].sum + tr[rs].L);
19 tr[p].R = max(tr[rs].R, tr[rs].sum + tr[ls].R);
20 tr[p].s = max(max(tr[ls].s, tr[rs].s), tr[ls].R + tr[rs].L);
21 }
22 void build(int p, int l, int r)
23 {
24 tr[p].l = l;
25 tr[p].r = r;
26 if(l == r)
27 {
28 tr[p].sum = num[l];
29 tr[p].L = num[l];
30 tr[p].R = num[l];
31 tr[p].s = num[l];
32 return;
33 }
34 int mid = l + r >> 1;
35 build(ls, l, mid);
36 build(rs, mid + 1, r);
37 update(p);
38 }
39 void modify_set(int p, int pos, int v)
40 {
41 if(tr[p].l == tr[p].r)
42 {
43 tr[p].sum = v;
44 tr[p].L = v;
45 tr[p].R = v;
46 tr[p].s = v;
47 return;
48 }
49 int mid = tr[p].l + tr[p].r >> 1;
50 if(pos <= mid) modify_set(ls, pos, v);
51 else modify_set(rs, pos, v);
52 update(p);
53 }
54 seg query(int p, int l, int r)
55 {
56 if(l <= tr[p].l && r >= tr[p].r)
57 {
58 return tr[p];
59 }
60 int mid = tr[p].l + tr[p].r >> 1;
61 seg lz = (seg){0, 0, 0, -inf, -inf, -inf};
62 seg rz = (seg){0, 0, 0, -inf, -inf, -inf};
63 seg ret;
64 if(l <= mid) lz = query(ls, l, r);
65 if(r > mid) rz = query(rs, l, r);
66 ret.sum = lz.sum + rz.sum;
67 ret.L = max(lz.L, lz.sum + rz.L);
68 ret.R = max(rz.R, rz.sum + lz.R);
69 ret.s = max(max(lz.s, rz.s), lz.R + rz.L);
70 return ret;
71 }
72 int main()
73 {
74 scanf("%d%d", &n, &m);
75 for(int i = 1; i <= n; i ++)
76 scanf("%d", &num[i]);
77 build(1, 1, n);
78 int op, a, b;
79 while(m --)
80 {
81 scanf("%d%d%d", &op, &a, &b);
82 if(op == 1)
83 {
84 if(a > b) swap(a, b);
85 printf("%d\n", query(1, a, b).s);
86 }
87 else modify_set(1, a, b);
88 }
89 return 0;
90 }
来源:https://www.cnblogs.com/loi-frank/p/12285257.html