hihoCoder
来源:互联网 发布:p值计算软件 编辑:程序博客网 时间:2024/06/03 13:52
ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 I
#1586 : Minimum
- 样例输入
131 1 2 2 1 1 2 251 0 71 1 22 1 22 2 21 1 2
- 样例输出
114
描述
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.
解题思路:线段树模板题……一开始以为x!=y,结果想用主席树去求第k大,后来才反应过来,x可以等于y,这样的话就很简单了。只需找出最大最小值即可。如果最小值为负数,最大值为正数,那么相乘即可。如果最小值为正数,那么就是最小值的平方。如果最大值为负数,那么就是最大值的平方。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int INF=1<<30;typedef long long int ll;const int maxn=200005;int treemax[maxn<<2];//线段树数组,看你要存什么int treemin[maxn<<2];//线段树数组,看你要存什么int A[maxn];//原数组,下标1~n//更新节点信息,这里是求最值void pushup(int rt){ treemax[rt]=max(treemax[rt<<1],treemax[rt<<1|1]);//<<1为*2.<<1|1为*2+1,即左子树和右子树 treemin[rt]=min(treemin[rt<<1],treemin[rt<<1|1]);//<<1为*2.<<1|1为*2+1,即左子树和右子树}//建树void build(int l,int r,int rt){//l,r表示当前区间,rt表示当前区间在线段树数组中的位置 if(l==r){//若到达叶子结点 treemax[rt]=A[l];//将该位置存原数组的值 treemin[rt]=A[l];//将该位置存原数组的值 return; } int m=(l+r)>>1;//>>1等于/2 //递归建树 build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt);//建完左右子树后,更新当前节点的值}//点修改,即A[L]=C,要同时修改相关区间的值,与建树同理,其实就是建树的过程void update(int L,int C,int l,int r,int rt){ if(l==r){//若到达叶节点,则修改叶节点的值 treemin[rt]=C; treemax[rt]=C; return; } int m=(l+r)>>1; //根据L判断是往哪个子树递归修改 if(L<=m) update(L,C,l,m,rt<<1);//左子树 else update(L,C,m+1,r,rt<<1|1);//右子树 pushup(rt);//子节点更新完了,那么可以更新自己了,即从下而上修改,建树同理}//查询,这里为求最值,LR代表要查询的区间,lr代表当前区间,rt表示当前节点在数组中的实际位置int querymax(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R)//如果当前区间在查询区间内,直接返回当前存的值 return treemax[rt]; int m=(l+r)>>1; //累加求答案 int ANS=-INF; if(L<=m)//如果左子区间与[L,R]有重叠,就递归左子树,右子树同理。 ANS=max(ANS,querymax(L,R,l,m,rt<<1)); if(R>m) ANS=max(ANS,querymax(L,R,m+1,r,rt<<1|1)); return ANS;}int querymin(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R)//如果当前区间在查询区间内,直接返回当前存的值 return treemin[rt]; int m=(l+r)>>1; //累加求答案 int ANS=INF; if(L<=m)//如果左子区间与[L,R]有重叠,就递归左子树,右子树同理。 ANS=min(ANS,querymin(L,R,l,m,rt<<1)); if(R>m) ANS=min(ANS,querymin(L,R,m+1,r,rt<<1|1)); return ANS;}int main(){ int t; int n,m; scanf("%d",&t); while(t--){ scanf("%d",&n); n=1<<n; for(int i=1;i<=n;i++) { scanf("%d",&A[i]); } build(1,n,1); scanf("%d",&m); int a,b,c; for(int i=0;i<m;i++){ scanf("%d%d%d",&c,&a,&b); a++; if(c==1){ b++; ll mmax=querymax(a,b,1,n,1); ll mmin=querymin(a,b,1,n,1); if(mmax<=0)printf("%lld\n",mmax*mmax); else if(mmin>=0) printf("%lld\n",mmin*mmin); else printf("%lld\n",mmin*mmax); } else{ update(a,b,1,n,1); } } } return 0;}
- hihocoder:
- hihoCoder
- Hihocoder
- hihocoder
- hihocoder
- hihocoder
- hihocoder
- hihocoder
- HihoCoder
- HihoCoder
- HihoCoder
- HihoCoder
- HihoCoder
- HihoCoder
- hihoCoder
- HihoCoder
- HihoCoder
- HihoCoder
- <Android 基础(零)> Android知识框架梳理
- 什么是嵌入式
- Matlab中如何使函数作为参数传递
- 多态
- 《C#图解教程》第5章 方法 读书笔记
- hihoCoder
- 前端性能优化
- hdu 1025 最大上升子序列
- Java中的引用及分类
- 关于弹出和隐藏输入法
- SpringMVC学习笔记(三)-----Controller拦截3种类型的URL
- 商城个性设置,Scrollview嵌套 多层recyclerview 切换、收起展开
- 安卓按键的回车换行符和读取写入txt文件的注意事项
- jsp入门