给你一个666

题目描述
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 = (010001 , 001011) = (21,13) = (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 1
5 2 3 4 5 6 7 8 1 6 5 1
1 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。

思路
直接枚举所有可能的情况,得到每一种[l,r]下的最值,最后根据已有数据得出结果

代码实现

#include<bits/stdc++.h>
using namespace std;

const int N=50005;
const int mod=1000000007;
typedef long long ll;


int l,r;
int n,q,num[N];
int Gmax[5005][5005],Gmin[5005][5005];

inline void judgel(int &x)
{
    if(x<1 || x>n) x=1;
}
inline void judger(int &x)
{
    if(x<1 || x>n) x=n;
}
void func(int a,int b)
{
    int ar,al,br,bl;
    ar=a>>3;
    al=a-(ar<<3);
    br=b>>3;
    bl=b-(br<<3);
    int c,d;
    c=ar*bl;
    d=al*br;
    if(c>d) swap(c,d);
    l=c*min(a,b);
    r=d*max(a,b);
    judgel(l);
    judger(r);
}
int findmax()
{
    int maxn=-1;
    for(int i=l;i<=r;i++)
    {
        maxn=max(maxn,num[i]);
    }
    return maxn;
}
int findmin()
{
    int minn=INT_MAX;
    for(int i=l;i<=r;i++)
    {
        minn=min(minn,num[i]);
    }
    return minn;
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
    }
    for(int i=0;i<=64;i++)
    {
        for(int j=0;j<=64;j++)
        {
            func(i,j);
            Gmax[l][r]=findmax();
            Gmin[l][r]=findmin();
        }
    }
    while(q--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        func(a,b);
        printf("%d %d\n",Gmax[l][r],Gmin[l][r]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值