ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 Minimum

题目链接
描述
You are given a list of integers a0, a1, …, a2^k-1.
You need to support two types of queries:

  1. Output Minx,y∈[l,r] {ax∙ay}.
  2. Let ax=y.
    输入
    The first line is an integer T, indicating the number of test cases. (1≤T≤10).
    For each test case:
    The first line contains an integer k (0 ≤ k ≤ 17).
    The following line contains 2^k integers, a0, a1, …, a2^k-1 (-2^k ≤ ai < 2^k).
    The next line contains a integer (1 ≤ Q < 2^k), indicating the number of queries. Then next Q lines, each line is one of:
  3. 1 l r: Output Minx,y∈[l,r]{ax∙ay}. (0 ≤ l ≤ r < 2^k)
  4. 2 x y: Let ax=y. (0 ≤ x < 2^k, -2^k ≤ y < 2^k)
    输出
    For each query 1, output a line contains an integer, indicating the answer.
    样例输入
    1
    3
    1 1 2 2 1 1 2 2
    5
    1 0 7
    1 1 2
    2 1 2
    2 2 2
    1 1 2
    样例输出
    1
    1
    4
    注意点:
    1.<<运算符
    举个例子:
    5<<2 将5转化为二进制为101,"<<"的意思就是将5的二进制向左移动两位,右边补零
    例子中移完之后,变成10100 结果就是20
    或者直接记公式:a<<b = a×2^b;
    2.>>运算符
    同理:a>>b = a ÷ 2 ^ b;
    3.线段树的节点数目要开存放数组最大限度的至少4倍(百度一下,你就知道)
    4.如果线段树的某个节点为segTree[i],那么左孩子节点为segTree[2i],右孩子节点为segTree[2i+1],原因:
    节点是从1开始的,例如第一个节点,没有第0个节点的说法
    5.剩下的解释都在代码里

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 150000;
LL t,k,q,z,w,e,mmn,mmx,a[N],mn[N << 2],mx[N << 2];
void build(int k,int l,int r){
	if(l == r){
		mn[k] = mx[k] = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(k * 2,l,mid);
	build(k * 2 + 1,mid + 1,r);
	mn[k] = min(mn[k * 2],mn[k * 2 + 1]);
	mx[k] = max(mx[k * 2],mx[k * 2 + 1]);
	return;
}
void update(int k,int l,int r,int L,int R){
	if(l == r){
		mn[k] = mx[k] = R;
		return;
	}
	int mid = l + r >> 1;
	if(mid >= L){
		update(k * 2,l,mid,L,R);
	}
	else{
		update(k * 2 + 1,mid + 1,r,L,R);
	}	
	mn[k] = min(mn[k * 2],mn[k * 2 + 1]);
	mx[k] = max(mx[k * 2],mx[k * 2 + 1]);
	return;
}
int query_min(int k,int l,int r,int L,int R){
	if(l > R || r < L){
		return INT_MAX;
	}
	if(L <= l && R >= r){
		return mn[k];
	}
	int mid = l + r >> 1;
	return min(query_min(k * 2,l,mid,L,R),query_min(k * 2 + 1,mid + 1,r,L,R));
}
int query_max(int k,int l,int r,int L,int R){
	if(l > R || r < L){
		return INT_MIN;
	}
	if(L <= l && R >= r){
		return mx[k];
	}
	int mid = l + r >> 1;
	return max(query_max(k * 2,l,mid,L,R),query_max(k * 2 + 1,mid + 1,r,L,R));
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> t;
	while(t--){
		cin >> k;
		k = pow(2,k);
		for(int i = 0;i < k;i++){//下标从0开始!!
			cin >> a[i];
		}
		build(1,0,k-1);
		cin >> q;
		while(q--){
			cin >> z >> w >> e;
			if(z == 1){
				mmn = query_min(1,0,k-1,w,e);
				mmx = query_max(1,0,k-1,w,e);
				if(mmn >= 0){
					cout << mmn * mmn << endl;
				}
				else if(mmx <= 0){
					cout << mmx * mmx << endl;
				}
				else{
					cout << mmn * mmx << endl;
				}
			}
			else{
				update(1,0,k-1,w,e);
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值