ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛-题目9 : Minimum-(线段树)

Minimum

时间限制: 1000ms
单点时限: 1000ms
内存限制: 256MB

描述

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 2k integers, a0, a1, …, a2^k-1 (-2k ≤ ai < 2k).

The next line contains a integer  (1 ≤ Q < 2k), indicating the number of queries. Then next Q lines, each line is one of:

1. 1 l r: Output Minx,y∈[l,r]{ax∙ay}. (0 ≤ l ≤ r < 2k)

2. 2 x y: Let ax=y. (0 ≤ x < 2k, -2≤ y < 2k)

输出

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.求区间内最小两个数的乘积,(一个点也是区间)。2.将x处的值改为y

解题要分情况讨论:如果区间内有正有负,最小乘积积就是最小(负数)与最大(正数)的乘积(结果为负数),如果区间内都正或都负结果就是绝对值最小的数的平方。题目维护三个线段树,分别求区间最小、最大、和绝对值最小的数。

要注意下标是从0开始

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;

#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn =131100;
int MAX[maxn<<2],MIN[maxn<<2],MID[maxn<<2];
int go(int a,int b)
{
    if(abs(a)> 1;
	build(lson);
	build(rson);
	PushUPmax(rt);
	PushUPmin(rt);
	PushUPmid(rt);
}
void update(int p,int sc,int l,int r,int rt) {
	if (l == r) {
		MIN[rt]=MID[rt]=MAX[rt] = sc;
		return ;
	}
	int m = (l + r) >> 1;
	if (p <= m) update(p , sc , lson);
	else update(p , sc , rson);
	PushUPmax(rt);
	PushUPmin(rt);
	PushUPmid(rt);
}
int querymin(int L,int R,int l,int r,int rt) {
	if (L <= l && r <= R) {
		return MIN[rt];
	}
	int m = (l + r) >> 1;
	int ret = maxn;
	if (L <= m) ret = min(ret , querymin(L , R , lson));
	if (R > m) ret = min(ret , querymin(L , R , rson));
	return ret;
}
int querymax(int L,int R,int l,int r,int rt) {
	if (L <= l && r <= R) {
		return MAX[rt];
	}
	int m = (l + r) >> 1;
	int ret = -maxn;
	if (L <= m) ret = max(ret , querymax(L , R , lson));
	if (R > m) ret = max(ret , querymax(L , R , rson));
	return ret;
}
int querymid(int L,int R,int l,int r,int rt) {
	if (L <= l && r <= R) {
		return MID[rt];
	}
	int m = (l + r) >> 1;
	int ret = maxn;
	if (L <= m) ret = go(ret , querymid(L , R , lson));
	if (R > m) ret = go(ret , querymid(L , R , rson));
	return ret;
}
int main() {
	int T,n,m;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        n=pow(2,n);
		build(1 , n , 1);
        scanf("%d",&m);
		while (m --)
        {
			int a , b , c;
			scanf("%d%d%d",&c,&a,&b);
            a++;
			if (c == 1)
			{
			    b++;
			    ll t1=(ll)querymin(a , b , 1 , n , 1);
			    ll t2=(ll)querymax(a , b , 1 , n , 1);
			    ll t3=(ll)querymid(a , b , 1 , n , 1);
			    ll ans;
			    //cout<=0)
                {
                    ans=t1*t2;
                    printf("%lld\n",ans);
                }
                else if(t1>0||t2<0)
                {
                    ans=t3*t3;
                    printf("%lld\n",ans);
                }
			}
			else update(a , b , 1 , n , 1);
		}
	}
	return 0;
}


你可能感兴趣的:(线段树,ACM比赛练习)