Problem E: QQ哥的数组
Time Limit: 5 Sec Memory Limit: 128 MB
Description
QQ哥很冷漠,他不想解释这么多,上来就给你四个数组ABCD编号为1234,初始状态下,每个数组的值都是0,然后给你两种操作
第一种操作:把某个数组某个位置的值改为某个值
第二种操作:区间查询某个公式的最值。
Input
每个输入只有一组数据
第一行是,两个整数N和Q代表四个数组的长度和操作的次数 (1<=N,Q<=100000)
接下来有Q行,每行先输入一个整数t,
当t==1时:输入三个整数 K,C,X,代表把第K个数组第C个位置的值改为X。(1<=K<=4,1<=C<=100000,-10000<=X<=10000)
当t==2时:输入两个整数 L,R,代表计算下标从L到R中 A[i]*B[i]*C[i]*D[i] 的最大值 (1<=L<=R<=N)
Output
对于每个t==2的查询,输出一个整数,代表答案。
Sample Input
5 10
1 1 1 2
1 2 1 2
1 3 1 2
1 4 1 2
2 1 5
1 1 1 0
2 1 5
1 1 1 5
2 1 5
2 1 1
Sample Output
16
0
40
40
HINT
题解:
裸的线段树最大值问题。
注意要把 query() 里的 ans 初始化为负无限大。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200010;
int n, q;
ll a[maxn<<2], b[maxn<<2], c[maxn<<2], d[maxn<<2], node[maxn<<2];
void pushup(int rt){
node[rt] = max(node[rt<<1], node[rt<<1|1]);
return ;
}
void build(int l, int r, int rt){
if(l==r){
a[rt] = 0;
b[rt] = 0;
c[rt] = 0;
d[rt] = 0;
node[rt]= a[rt] * b[rt] * c[rt] * d[rt];
return ;
}
int mid = l + r >> 1;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
pushup(rt);
}
void update(int k, int L, int R, int x, int l, int r, int rt){
if(L<=l&&r<=R){
if(k==1){
a[rt] = x;
}
else if(k==2){
b[rt] = x;
}
else if(k==3){
c[rt] = x;
}
else {
d[rt] = x;
}
node[rt]= a[rt] * b[rt] * c[rt] * d[rt];
return ;
}
int mid = l + r >> 1;
if(L<=mid)update(k, L, R, x, l, mid, rt<<1);
if(mid<R)update(k, L, R, x, mid+1, r, rt<<1|1);
pushup(rt);
}
ll query(int L, int R, int l, int r, int rt){
if(L<=l&&r<=R){
return node[rt];
}
int mid = l + r >> 1;
ll ans = -1e20;
if(L<=mid){
ans = max(ans, query(L, R, l, mid, rt<<1));
}
if(mid<R){
ans = max(ans, query(L, R, mid+1, r, rt<<1|1));
}
return ans;
}
int main(){
scanf("%d %d", &n, &q);
build(1, n, 1);
int op;
while(q--){
scanf("%d", &op);
if(op==1){
int k, c, x;
scanf("%d %d %d", &k, &c, &x);
update(k, c, c, x, 1, n, 1);
}
else{
int l, r;
scanf("%d %d", &l, &r);
printf("%lld\n", query(l, r, 1, n, 1));
}
}
return 0;
}