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

来源:互联网 发布:淘宝可以延长几天收货 编辑:程序博客网 时间:2024/05/22 13:07

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.

样例输入
131 1 2 2 1 1 2 251 0 71 1 22 1 22 2 21 1 2
样例输出
114
线段树的简单题目,刚好学到线段树,也刚好题目不难,

题目有两种操作:1.求区间内最小两个数的乘积,(一个点也是区间)。2.将x处的值改为y

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

要注意下标是从0开始

代码:

#include<iostream>#include<string>#include<cstdio>#include<algorithm>#include<cmath>#include<iomanip>#include<queue>#include<cstring>#include<map>#include<vector>using namespace std;typedef long long ll;#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1const int maxn =131100;int MAX[maxn<<2],MIN[maxn<<2],MID[maxn<<2];int go(int a,int b){    if(abs(a)<abs(b))        return a;    else return b;}void PushUPmax(int rt) {MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]);}void PushUPmin(int rt) {MIN[rt] = min(MIN[rt<<1] , MIN[rt<<1|1]);}void PushUPmid(int rt) {MID[rt] = go(MID[rt<<1] , MID[rt<<1|1]);}void build(int l,int r,int rt) {if (l == r) {scanf("%d",&MAX[rt]);MIN[rt]=MID[rt]=MAX[rt];return ;}int m = (l + r) >> 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<<t1<<" "<<t2<<endl;    if(t1<=0&&t2>=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;}


阅读全文
0 0