题目9 : Minimum
-
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
样例输出
描述
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, -2k ≤ y < 2k)
输出
For each query 1, output a line contains an integer, indicating the answer.
1 1 4题意:查询给定区间两个数字乘积的最小值注意数字存在负数!!!!!首先求出该区间的最小值和最大值,若最小值大于等于0,那么数字乘积的最小值就是最小值的平方;反之,如果最大值小于0,那乘积的最小值一定是正的,即为最大值的平方,否则就为最小值和最大值的乘积求区间最值问题并修改 则用树状数组 或 线段树代码如下:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef long long int ll; const int MAXN =131084;
const int INF=0x3f3f3f3f;
ll a[MAXN], h[MAXN], l[MAXN];
ll n,m;
ll pow1(ll a,ll b)
{ll res=1,base=a;while(b){if(b&1)res*=base;base*=base;b=b>>1;}return res;
} ll lowbit(ll x)
{ return x & (-x);
}
void updata_min(ll x)
{ ll lx, i; while (x <= n) { h[x] = a[x]; lx = lowbit(x); for (i=1; i<lx; i<<=1) h[x] = min(h[x], h[x-i]); x += lowbit(x); }
}
void updata_max(ll x)
{ll lx, i; while (x <= n) { l[x] = a[x]; lx = lowbit(x); for (i=1; i<lx; i<<=1) l[x] = max(l[x], l[x-i]); x += lowbit(x); }
}
ll query_max(ll x, ll y)
{ ll ans = -INF; while (y >= x) { ans = max(a[y], ans); y --; for (; y-lowbit(y) >= x; y -= lowbit(y)) ans = max(l[y], ans); } return ans;
}
ll query_min(ll x, ll y)
{ ll ans = INF; while (y >= x) { ans = min(a[y], ans); y --; for (; y-lowbit(y) >= x; y -= lowbit(y)) ans = min(h[y], ans); } return ans;
}
int main()
{ ll i, j, x, y, ans_min,ans_max; char c; int t; scanf("%d",&t);while(t--){scanf("%lld",&n);n=pow1(2,n);for (i=1; i<=n; i++) h[i] = 0; for (i=1;i<=n;i++)l[i] = 0;for (i=1; i<=n; i++) { scanf("%lld",&a[i]); updata_min(i); updata_max(i);} scanf("%d",&m);for (i=1; i<=m; i++) { int p;scanf("%d%lld%lld",&p,&x,&y); //cout<<p<<endl;//cout<<endl;if(p==1) {ans_min = query_min(x+1,y+1);//ans_max = query_max(x+1,y+1);//cout<<ans_min<<" "<<ans_max<<endl; if(ans_min>=0)printf("%lld\n",ans_min*ans_min);else{ans_max = query_max(x+1 ,y+1);if(ans_max<=0)printf("%lld\n",ans_max*ans_max);else printf("%lld\n",ans_min*ans_max); }}else{a[x+1]=y;updata_min(x+1);updata_max(x+1);}} } return 0;
}