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

题目9 : 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的话输出 x--y区间最小的乘积  2是让a[x]=y;算是修改点

直接求区间最大最小值和修改单点 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=150005;
const int maxx=0x3f3f3f3f;
long long  h[maxn],a[maxn],b[maxn];
long long n,m;
long long pow1(long long a,long long b)
{
	long long ans=1;
	long long aa=a;
	while(b)
	{
		if(b&1)
			ans=ans*aa;
		aa=aa*aa;
		b=b/2;
	}
	return ans;
 } 
long long lowbit(long long  x)
{
    return  x & (-x);
}
void updatemax(long long  x)//a 是max 
{
	long long i,temp;
    while(x<=n)
    {
        a[x]=h[x];
        temp=lowbit(x);
        for(i=1;i<temp;i<<=1)
        	a[x]=max(a[x],a[x-i]);
        x+=lowbit(x);
    }
}
void updatemin(long long  x)//b 存小的 
{
	long long i,temp;
    while(x<=n)
    {
        b[x]=h[x];
        temp=lowbit(x);
        for(i=1;i<temp;i<<=1)
        	b[x]=min(b[x],b[x-i]);
        x+=lowbit(x);
    }
}
long long  findansmax(long long  begin,long long end)
{
    long long  ans=-maxx;
    while(end>=begin)
    {
        ans=max(ans,h[end]);
        end--;
        for(;end-lowbit(end)>=begin;end-=lowbit(end))
        	ans=max(ans,a[end]);	
	}
	return ans;
}
long long  findansmin(long long  begin,long long  end)
{
    long long  ans=maxx; 
    while(end>=begin)
    {
        ans=min(ans,h[end]);
        end--;
        for(;end-lowbit(end)>=begin;end-=lowbit(end))
        	ans=min(ans,b[end]);	
	}
	return ans;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
  		scanf("%lld",&n);
		n=pow1(2,n);
      	memset(a,0,sizeof(a));
      	memset(b,0,sizeof(b));
        for(long long  i=1;i<=n;i++)
        {
            scanf("%lld",&h[i]);
            updatemin(i);
            updatemax(i);
        }
        scanf("%lld",&m);
        int q;
		long long x,y;
        for(long long  i=1;i<=m;i++)
        {
            scanf("%d%lld%lld",&q,&x,&y);
            if(q==2)//update
            {
                h[x+1]=y;
                updatemin(x+1);
                updatemax(x+1);
            }
            else 
            {
                long long ans_1=findansmin(x+1,y+1);
                long long ans_2=findansmax(x+1,y+1);
                if(ans_1>=0)//同时大于等于0 
                	printf("%lld\n",ans_1*ans_1);
                else//ans_1 <0
                {
                	if(ans_2<=0)
                		printf("%lld\n",ans_2*ans_2);
                	else
                		printf("%lld\n",ans_1*ans_2);
				}
            }
        }
    }
    return 0;
}

其实也就是几个板子套一块~好好理解每一个函数是干嘛用的~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值