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