题意:
输入2^n个数将这些数分为好多个区间,询问这个区间里的最小值,最小值为区间里的某个数与某个数相乘(可以相同),q次询问可以 输入1 代表求吃某个区间的某个值,2代表单点修改 区间里的某个点的值
思路:一开始用的是单调队列,以为能水过,没想到超时时间是O(n*m)的复杂度会超时,还是得用log(n)的复杂度,线段树才能过
其实学了线段树,单调队列基本上就不用学了,但单调队列也是一种简单的代码,线段树能解决好多问题,包括二分的思想的题
WA 代码:
#include<bits/stdc++.h>
using namespace std;
//单调队列
int k=3,n;
int q1[150000],q2[150000];
int a[150000];
int slove_min(int l,int r)
{
int head=l,tail=l-1;
for(int i=l; i<r; i++)
{
while(head<=tail&&a[q1[tail]]>a[i])//最小元素更新到队首
tail--;
q1[++tail]=i;
}
return a[head];
}
int slove_max(int l,int r)
{
int head=l,tail=l-1;
for(int i=l; i<r; i++)
{
while(head<=tail&&a[q2[tail]]<a[i])//最大元素更新到队首
tail--;
q2[++tail]=i;
}
return a[head];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,k;
scanf("%d",&k);
n=(int)pow(2,k);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
//printf("%d",slove_min(0,7));
int q;
scanf("%d",&q);
while(q--)
{
int judge,r,l,maxx,minx;
scanf("%d %d %d",&judge,&l,&r);
if(judge==1)
{
maxx=slove_max(l,r);
minx=slove_min(l,r);
if(minx>=0)
printf("%d\n",minx*minx);
else if(maxx<=0)
printf("%d\n",maxx*maxx);
else if(maxx>0&&minx<0)
printf("%d\n",maxx*minx);
}
else
{
a[l]=r;
}
}
}
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
//线段树
#define N 150000
#define ll long long
ll a[N];
struct node
{
ll l,r,maxx,minx;
}tree[4*N+10];
void update(ll k)
{
tree[k].maxx=max(tree[k*2+1].maxx,tree[k*2].maxx);
tree[k].minx=min(tree[k*2+1].minx,tree[k*2].minx);
}
void build(ll k,ll l,ll r)
{
tree[k].l=l,tree[k].r=r;
if(l==r)
{
tree[k].maxx=a[l];
tree[k].minx=a[l];
return ;
}
ll mid=(l+r)/2;
build(k*2,l,mid);//左孩子
build(k*2+1,mid+1,r);//右孩子
update(k);
}
void change(ll k,ll x,ll y)
{
if(tree[k].l==tree[k].r)
{
tree[k].maxx=y;
tree[k].minx=y;
return ;
}
ll mid=(tree[k].l+tree[k].r)/2;
if(mid>=x)
change(k*2,x,y);//在左区间
else
change(k*2+1,x,y);//在右区间
update(k);
}
ll query_max(ll k,ll l,ll r)
{
if(tree[k].l>=l&&tree[k].r<=r)
{
return tree[k].maxx;
}
ll mid=(tree[k].l+tree[k].r)/2;
if(mid>=r)
return query_max(k*2,l,r);
if(mid<l)
return query_max(k*2+1,l,r);
return max(query_max(k*2,l,r),query_max(k*2+1,l,r));
}
ll query_min(ll k,ll l,ll r)
{
if(tree[k].l>=l&&tree[k].r<=r)
{
return tree[k].minx;
}
ll mid=(tree[k].l+tree[k].r)/2;
if(mid>=r)
return query_min(k*2,l,r);
if(mid<l)
return query_min(k*2+1,l,r);
return min(query_min(k*2,l,r),query_min(k*2+1,l,r));
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
ll n,k;
scanf("%lld",&k);
n=(ll)pow(2,k);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
//printf("%d",slove_min(0,7));
build(1,1,n);
ll q;
scanf("%lld",&q);
while(q--)
{
ll judge,r,l,maxx,minx;
scanf("%lld %lld %lld",&judge,&l,&r);
if(judge==1)
{
maxx=query_max(1,l+1,r+1);
minx=query_min(1,l+1,r+1);
if(minx>0)
printf("%lld\n",minx*minx);
else if(maxx>0)
printf("%lld\n",maxx*minx);
else
printf("%lld\n",maxx*maxx);
}
else
{
change(1,l+1,r);
}
}
}
}