2017ICPC北京赛区网络赛 Minimum(数学+线段树)
Posted Annetree的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017ICPC北京赛区网络赛 Minimum(数学+线段树)相关的知识,希望对你有一定的参考价值。
描述
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 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.最大值的平方(最大值为负数)
2.最小值的平方(最小值为正数)
3.最大值与最小值的乘积(最大值是正,最小值为负)
得到此结果后,只需改一下线段树的模板,将每段区间的最大最小值保存下来即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 const long long Max=140000; 7 int n; 8 struct node 9 { 10 long long b,s; 11 }Tree[Max<<2]; 12 long long bb,ss; 13 void build(int k,int l,int r)//建线段树,k表示子节点坐标 14 { 15 if(l == r) 16 { 17 scanf("%lld",&Tree[k].b); 18 Tree[k].s=Tree[k].b; 19 } 20 else 21 { 22 int mid = (l+r)/2; 23 build(k*2,l,mid); 24 build(k*2+1,mid+1,r); 25 Tree[k].b=max(Tree[k*2].b, Tree[k*2+1].b); 26 Tree[k].s=min(Tree[k*2].s, Tree[k*2+1].s); 27 } 28 } 29 void query(int a,int b,int k,int l,int r)//a,b是当前查询区间,k是当前的根节点,l,r是要求查询区间 30 { 31 if(a >= l && b <= r) 32 { 33 bb=max(bb,Tree[k].b); 34 ss=min(ss,Tree[k].s); 35 //return min(min(Tree[k].b*Tree[k].b,Tree[k].b*Tree[k].s),Tree[k].s*Tree[k].s); 36 return; 37 } 38 else 39 { 40 //long long ans = Max*Max; 41 int mid = (a+b)/2; 42 if(l <= mid)query(a,mid,k*2,l,r); 43 if(r > mid) query(mid+1,b,k*2+1,l,r); 44 return; 45 //return ans; 46 } 47 } 48 void update(int l,int r,int k,int pos,long long v)//l,r是查询区间,k是当前根节点,pos是查询位置 49 { 50 if(l == r) 51 { 52 Tree[k].b=v; 53 Tree[k].s=v; 54 } 55 else{ 56 int mid = (l+r)/2; 57 if(pos <= mid) update(l,mid,k*2,pos,v); 58 if(pos > mid) update(mid+1,r,k*2+1,pos,v); 59 Tree[k].b=max(Tree[k*2].b, Tree[k*2+1].b); 60 Tree[k].s=min(Tree[k*2].s, Tree[k*2+1].s); 61 } 62 } 63 64 int main() 65 { 66 int T,l,r,pos; 67 long long val; 68 int k,c,order; 69 scanf("%d",&T); 70 for(int t=1;t<=T;t++) 71 { 72 73 scanf("%d",&k); 74 n=pow(2.0,k); 75 build(1,1,n); 76 scanf("%d",&c); 77 while(c--) 78 { 79 scanf("%d",&order); 80 if(order==1) 81 { 82 scanf("%d%d",&l,&r); 83 bb=-Max;ss=Max; 84 long long tmpans; 85 query(1,n,1,l+1,r+1); 86 tmpans= min(min(bb*bb,bb*ss),ss*ss); 87 printf("%lld\n",tmpans); 88 } 89 else if(order==2)//点更新 90 { 91 scanf("%d%lld",&pos,&val); 92 update(1,n,1,pos+1,val); 93 } 94 } 95 } 96 return 0; 97 }
以上是关于2017ICPC北京赛区网络赛 Minimum(数学+线段树)的主要内容,如果未能解决你的问题,请参考以下文章
ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 hihocoder #1586 : Minimum-区间查询最值求区间两数最小乘积+单点更新-线段树(结构体版)
ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 题目9 : Minimum
ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 i题 Minimum(线段树)
hihocoder 1586 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛-题目9 : Minimum线段树