广东外语外贸大学第15届程序设计竞赛 - E QQ哥的数组 - 线段树

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值