
给你一个666(线段树求最大最小值)
发布日期:2021-05-10 16:09:32
浏览次数:20
分类:精选文章
本文共 3002 字,大约阅读时间需要 10 分钟。
问题 C: 给你一个666
时间限制: 1 Sec 内存限制: 256 MB
提交: 342 解决: 60 [] [] [命题人:]题目描述
Tongtong非常喜欢用“say 666”的方式来打招呼,因此热爱数学的他找到了一个说666的新方式。Tongtong构造了一个数学上很6的运算。定义一个6位二进制数上的运算 @ : a@b=(c,d)。其中 c = a的高3位*b的低3位 ; d = a的低3位*b的高3位。例如 010 001 @ 011 001 = (010*001 , 001*011) = (2*1,1*3) = (2,3) 。
Tongtong给出了两个操作数a和b。以及一个数列 x1,x2,x3 ... xn ,假设a@b的结果(c,d),Tongtong非常关心数列在区间 [ min(c,d)*min(a,b) ,max(c,d)*max(a,b) ]上的最小值和最大值,Tongtong认为上述区间上的最大值和最小值可以代表666的程度,所以每组操作数都要计算出这两个最值。由于时间紧迫,他需要你来帮助他完成这个工作。
输入
第一行输入两个正整数 n,q,分别表示数列数字的个数和询问个数.其中1<=n<=50 000,1<=q<=100 000。
第二行输入n个非负整数,表示数列中的元素x1,x2 ... xn, 每个元素都在int类型的范围内。 接下来q行,每行给出一对非负整数,a,b,其意义见题面。本题保证所有的a和b均为6位无符号整数。
输出
对于每个询问,输出一对整数,分别表示目标区间上的最大值和最小值.每个询问的结果单独占一行。
请不要输出多余的空行。
样例输入
复制样例数据
12 15 2 3 4 5 6 7 8 1 6 5 11 8
样例输出
8 2
提示
min(x,y)表示x和y的最小值, max(x,y)表示x和y的最大值.区间下标从1开始。
样例: 数列在区间[1,8]上的所有元素为{5 2 3 4 5 6 7 8},最大值为8,最小值为2。 若左边界越界则取1,若右边界越界则取n。
题意:中文题不解释
题解:就是求区间最大最小值,用到了线段树来优化,有一个巨坑的地方,看代码你会懂得~~(只要你被这个地方坑了)
上代码:
#include#include using namespace std;const int mod = 1e9+7;const int inf = 0x3f3f3f3f;typedef long long ll;const int MAX = 1e5+10;int a[MAX];int man,mnn;struct node{ int minn,maxx,left,right;}tree[MAX<<2];void build(int k,int l,int r)//建立线段树{ tree[k].left=l;tree[k].right=r; tree[k].maxx=tree[k].minn=0; if(l==r) return; int mid=(l+r)>>1; build(k<<1, l, mid); build(k<<1|1, mid+1, r);} void update(int k,int pos,int height) //更新线段树{ int l=tree[k].left,r=tree[k].right; if(l==r){ tree[k].maxx=tree[k].minn=height; return; } int mid=(l+r)>>1; if(pos<=mid) update(k<<1, pos, height); else update( k<<1|1, pos, height); tree[k].maxx=max(tree[k<<1].maxx,tree[k<<1|1].maxx); tree[k].minn=min(tree[k<<1].minn,tree[k<<1|1].minn);} void conut(int k,int ll,int rr)//统计范围内最大值以及最小值{ int l=tree[k].left,r=tree[k].right; if(ll<=l&&rr>=r){ man=max(man, tree[k].maxx); mnn=min(mnn,tree[k].minn); return; } int mid=(l+r)>>1; if(ll<=mid) conut(k<<1, ll, rr); if(rr>mid) conut(k<<1|1,ll, rr);}int main(){ int n,k; scanf("%d%d",&n,&k); build(1, 1, n); for (int i = 1; i <= n;i++){ scanf("%d",&a[i]); update(1, i, a[i]); } while(k--){ mnn=inf; man=0; int l,r; scanf("%d%d",&l,&r); int ls,rs; ls=l; rs=r; int cnt1=1; int cnt2=1; int ll[10],rr[10]; int lz[10],rz[10]; while(l){ if(l%2) ll[cnt1++]=1; else ll[cnt1++]=0; l>>=1; } while(cnt1!=7){ ll[cnt1++]=0; } for (int i = 6; i >= 1;i--){ lz[6-i+1]=ll[i]; } while(r){ if(r%2) rr[cnt2++]=1; else rr[cnt2++]=0; r>>=1; } while(cnt2!=7){ rr[cnt2++]=0; } for (int i = 6; i >= 1;i--){ rz[6-i+1]=rr[i]; } int x1,x2,y1,y2; x1=lz[1]*4+lz[2]*2+lz[3]; x2=lz[4]*4+lz[5]*2+lz[6]; y1=rz[1]*4+rz[2]*2+rz[3]; y2=rz[4]*4+rz[5]*2+rz[6]; int c,d; c=x1*y2; d=x2*y1; int minnl,maxxr; minnl=min(c,d)*min(ls,rs); if(minnl<1||minnl>n) minnl=1;//巨坑位置 maxxr=max(c,d)*max(ls,rs); if(maxxr>n||maxxr<1) maxxr=n;//巨坑位置 conut(1,minnl,maxxr); printf("%d %d\n",man,mnn); } return 0;}
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年04月16日 20时18分57秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
OpenCV camshift目标追踪
2021-05-10
Redis缓存穿透和缓存雪崩
2021-05-10
day04_CSS选择器
2021-05-10
python基础语法
2021-05-10
const修饰指针(常量指针与指针常量的区别)
2021-05-10
设计模式-创建型02-工厂模式-工厂方法模式01
2021-05-10
微信小程序sort时间排序
2021-05-10
<s>
2021-05-10
常见错误
2021-05-10
Oracle
2021-05-10
序列化与反序列化
2021-05-10
如何使用linux系统自带的led驱动
2021-05-10
泛知识类视频会改变短视频行业格局吗?
2021-05-10
IP-Guard回收客户端加密授权,已经加密的文档如何解密
2021-05-10
第十一节 IO编程
2021-05-10
十八、flask之g对象
2021-05-10
GIT学习笔记
2021-05-10
Linux系统调用过程
2021-05-10
stm32 uv5打开uv4工程错误
2021-05-10
mysql怎么终止一个事务_MySql 中游标,事务,终止存储过程方法总结
2021-05-10