C Data Structure Problem
链接:https://ac.nowcoder.com/acm/contest/7502/C
题目来源:牛客网
题目描述
Bobo has two sequences a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an and b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,…,bn. He would like to perform the following operations:
- 1 x y \text{1 }x\ y 1 x y, change the value of a x a_x axto y.
- 2 x y \text{2 }x\ y 2 x y, change the value of b x b_x bxto y.
- 3 x \text{3 }x 3 x, find the value of c x c_x cx, where c 0 = 0 c_0=0 c0=0, c i = max ( c i − 1 + b i , a i ) for 1 ≤ i ≤ x c_i=\max(c_{i-1}+b_i,a_i) \text{ for } 1 \le i \le x ci=max(ci−1+bi,ai) for 1≤i≤x
输入描述:
The input consists of several test cases terminated by end-of-file. For each test case:
The first line contains two integers n and m , which are the length of the two sequences and the number of operations. The second line contains n integers
a
1
,
a
2
,
…
,
a
n
a_1, a_2, \ldots, a_n
a1,a2,…,an . The third line contains n integers
b
1
,
b
2
,
…
,
b
n
b_1, b_2, \ldots, b_n
b1,b2,…,bn. Each of the last m lines contains a query.
- 1 ≤ n , m ≤ 2 × 1 0 5 1 \leq n, m \leq 2 \times 10^5 1≤n,m≤2×105
- − 1 0 9 ≤ a i , b i , y ≤ 1 0 9 -10^9 \leq a_i, b_i, y \leq 10^9 −109≤ai,bi,y≤109
- 1 ≤ x ≤ n 1 \leq x \leq n 1≤x≤n
- The sum of n and the sum of m do not exceed 2 × 1 0 6 2 \times 10^6 2×106.
输出描述:
For each query of \text{3 }x3 x, output an integer denoting the value of c x c_x cx.
示例
4 9
1 2 3 3
-1 2 3 3
3 1
3 2
3 3
3 4
2 2 -4
3 1
3 2
3 3
3 4
输出
1
3
6
9
1
2
5
8
思路
很容易想到对于每个3 x询问,你将输出一个
a
i
+
b
i
+
1
+
…
+
b
t
a_i+b_{i+1}+\ldots+b_{t}
ai+bi+1+…+bt,当然,如果
i
=
t
i=t
i=t也是有可能的。所以首先想到的是,用前缀和维护
b
i
b_i
bi(于是,在比赛的时候我卡住了)。那么,
a
n
s
x
=
m
a
x
i
x
(
a
i
+
S
x
−
S
i
)
=
S
x
+
m
a
x
i
x
(
a
i
−
S
i
)
ans_x=max^x_i(a_i+S_x-S_i)=Sx+max^x_i(a_i-S_i)
ansx=maxix(ai+Sx−Si)=Sx+maxix(ai−Si)。对于这个公式,只要用线段树维护
a
i
−
S
i
a_i-S_i
ai−Si即可。
对于操作1,单点修改a[x]即可;
对于操作2,区间修改sumb[x]-sumb[n];
对于询问3,区间1~x取出
m
a
x
(
a
i
−
S
i
)
max(a_i-S_i)
max(ai−Si)在加上
S
x
S_x
Sx即可。但注意,我们的
S
x
S_x
Sx是没有维护过的,因此我们需要利用维护好的线段树结果算出
S
x
=
a
[
x
]
−
t
r
x
S_x=a[x]-tr_x
Sx=a[x]−trx。
ac代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iomanip>
using namespace std;
#define LL long long
#define MOD 1000000007
#define MAXN 10000007
const int INF = 0x3f3f3f3f;
const int N = 200010;
LL read()
{
LL w = 1, x = 0;
char ch = 0;
while (ch < '0' || ch>'9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + (ch - '0');
ch = getchar();
}
return w * x;
}
LL sumb[N], a[N], b[N];
LL la[N << 2], tr[N << 2];
int n, m;
void build(int l, int r, int n)
{
la[n] = 0;
if (l == r)
{
tr[n] = a[l] - sumb[l];
return;
}
int mid = (l + r) >> 1;
build(l, mid, n << 1);
build(mid + 1, r, n << 1 | 1);
tr[n] = max(tr[n << 1], tr[n << 1 | 1]);
}
void pushdown(int n)
{
if (la[n] == 0)
{
return ;
}
tr[n << 1] += la[n];
tr[n << 1 | 1] += la[n];
la[n << 1] += la[n];
la[n << 1 | 1] += la[n];
la[n] = 0;
return;
}
void add(int al, int ar, LL x, int l, int r, int n)
{
if (al <= l && r <= ar)
{
tr[n] += x;
la[n] += x;
return;
}
pushdown(n);
int mid = (l + r) >> 1;
if (al <= mid)
{
add(al, ar, x, l, mid, n << 1);
}
if (ar > mid)
{
add(al, ar, x, mid + 1, r, n << 1 | 1);
}
tr[n] = max(tr[n << 1], tr[n << 1 | 1]);
}
LL query(int al, int ar, int l, int r, int n)
{
if (al <= l && r <= ar)
{
return tr[n];
}
pushdown(n);
int mid = (l + r) >> 1;
int fl = 0;
LL ans = 0;
if (al <= mid)
{
fl = 1;
ans = query(al, ar, l, mid, n << 1);
}
if (ar > mid)
{
if (fl)
{
ans = max(ans, query(al, ar, mid + 1, r, n << 1 | 1));
}
else
{
ans = query(al, ar, mid + 1, r, n << 1 | 1);
}
}
tr[n] = max(tr[n << 1], tr[n << 1 | 1]);
return ans;
}
int main()
{
while (cin >> n >> m)
{
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &a[i]);
}
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &b[i]);
sumb[i] = sumb[i - 1] + b[i];
}
build(1, n, 1);
for (int i = 1; i <= m; ++i)
{
int qqq, x;
LL y;
scanf("%d", &qqq);
if (qqq == 1)
{
scanf("%d %lld", &x, &y);
add(x, x, y - a[x], 1, n, 1);
a[x] = y;
}
else if (qqq == 2)
{
scanf("%d %lld", &x, &y);
add(x, n, -(y - b[x]), 1, n, 1);
b[x] = y;
}
else if (qqq == 3)
{
scanf("%d", &x);
LL res = max(0LL, query(1, x, 1, n, 1));
res += (a[x] - query(x, x, 1, n, 1));
printf("%lld\n", res);
}
}
}
return 0;
}