题目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
样例输出
-
1 1
4
-
分析:x,y属于区间[l,r],求最小的ax*ay,分一下情况,五种情况 [-,-] [-,0] [-,+] [0,+] [+,+]
-
查询操作次数最大有2^17=131072, 因此每次操作必须在常数时间o(n)内算出结果,因此要用到线段树
-
-
AC代码如下:
-
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; const int MAXN=200001; typedef long long llint; struct Tree{ int l,r,s; }nod[MAXN*4]; int a[MAXN]; void creat (int t,int l,int r) { nod[t].l=l; nod[t].r=r; if(l==r){ nod[t].s=a[l]; return; } int m=(l+r)/2; creat(t*2,l,m); creat(t*2+1,m+1,r); nod[t].s=min(nod[t*2].s,nod[t*2+1].s); } void update (int t,int n,int v)//把n点的值更新为v; { if(nod[t].r==nod[t].l&&nod[t].r==n) { nod[t].s=v; return; } int mid = (nod[t].l+nod[t].r)>>1; if(n<=mid) update (t*2,n,v); else update(2*t+1,n,v); nod[t].s=min(nod[2*t].s,nod[2*t+1].s); } int query(int t,int l,int r){ if(l==nod[t].l&&r==nod[t].r) return nod[t].s; int mid = (nod[t].l+nod[t].r)>>1; if(r<=mid) return query(t*2,l,r); else if(l>mid) return query(2*t+1,l,r); else return min(query(2*t,l,mid),query(t*2+1,mid+1,r)); } struct Tree1{ int l,r,s; }nod1[MAXN*4]; void creat1 (int t,int l,int r) { nod1[t].l=l; nod1[t].r=r; if(l==r){ nod1[t].s=a[l]; return; } int m=(l+r)/2; creat1(t*2,l,m); creat1(t*2+1,m+1,r); nod1[t].s=max(nod1[t*2].s,nod1[t*2+1].s); } void update1(int t,int n,int v)//把n点的值更新为v; { if(nod1[t].r==nod1[t].l&&nod1[t].r==n) { nod1[t].s=v; return; } int mid = (nod1[t].l+nod1[t].r)>>1; if(n<=mid) update1 (t*2,n,v); else update1(2*t+1,n,v); nod1[t].s=max(nod1[2*t].s,nod1[2*t+1].s); } int query1(int t,int l,int r){ if(l==nod1[t].l&&r==nod1[t].r) return nod1[t].s; int mid = (nod1[t].l+nod1[t].r)>>1; if(r<=mid) return query1(t*2,l,r); else if(l>mid) return query1(2*t+1,l,r); else return max(query1(2*t,l,mid),query1(t*2+1,mid+1,r)); } int main(){ int N; cin>>N; while(N--) { int n,m,i,x1,x2; int s; cin>>n; int num=pow(2.0,n); for(i=1;i<=num;i++) scanf("%d",&a[i]); creat(1,1,pow(2.0,n)); creat1(1,1,pow(2.0,n)); cin>>m; while(m--){ scanf("%d%d%d",&s,&x1,&x2); if(s==1) { int mini=query(1,x1+1,x2+1);//查最小值 int maxi=query1(1,x1+1,x2+1);//查最大值 if(mini<0 && maxi<0) cout<<(llint)maxi*maxi<<endl; else if(mini>0 && maxi>0) cout<<(llint)mini*mini<<endl; else if(mini<0 && maxi>0) cout<<(llint)maxi*mini<<endl; else if(maxi==0) cout<<0<<endl; else if(mini==0) cout<<0<<endl; } else { update(1,x1+1,x2);//更新 update1(1,x1+1,x2);//更新 } } } return 0; }
描述
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.