• 给你一个666


    问题 C: 给你一个666

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 375  解决: 69

    题目描述

    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 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。

    友好型解法:由于a,b都是6位二进制数,所以所有的情况只有2^16=4k种,枚举预处理出所有的a,b对应的最值,询问时直接输出即可
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct node
    {
        int pos,v;
    }s[50010];
    int n,t;
    bool cmp(node d,node f)
    {
        if(d.v!=f.v) return d.v<f.v;
        else return d.pos<f.pos;
    }
    map<pair<int,int>,pair<int,int> >m;
    void mul(int l,int r,int &x,int &y)
    {
        int a1=0,a2=0,b1=0,b2=0,tx,ty;
        a1=l>>3;
        a2=l-(a1<<3);
        b1=r>>3;
        b2=r-(b1<<3);
        tx=a2*b1,ty=a1*b2;
        x=min(tx,ty)*l;
        if(x<1||x>n) x=1;
        y=max(tx,ty)*r;
        if(y<1||y>n) y=n;
    }
    int main()
    {
        cin>>n>>t;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&s[i].v);
            s[i].pos=i;
        }
        sort(s+1,s+1+n,cmp);
        for(int i=0;i<1<<7;i++)
        {
            for(int j=i;j<1<<7;j++)
            {
                int x,y;
                mul(i,j,x,y);
                int p,q;
                for(int ii=1;ii<=n;ii++)
                {
                    if(s[ii].pos>=x&&s[ii].pos<=y)
                    {
                        p=s[ii].v;
                        break;
                    }
                }
                for(int ii=n;ii>=1;ii--)
                {
                    if(s[ii].pos>=x&&s[ii].pos<=y)
                    {
                        q=s[ii].v;
                        break;
                    }
                }
                m[make_pair(i,j)]=make_pair(q,p);
            }
        }
        while(t--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x>y) swap(x,y);
            printf("%d %d
    ",m[make_pair(x,y)].first,m[make_pair(x,y)].second);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    [原]RHCS集群的服务切换测试札记
    [原]从Clustering Factor说起
    命令行下设置IP地址的方法
    [原]SQL Server 2005 链接服务器使用一例
    [原]Oracle删除大表并回收空间的过程
    [转]从沙子到芯片:且看处理器是怎样炼成的
    [原] 在域环境中打开SSMS非常慢
    [原]将特定格式的string转换为DateTime
    [原] 在域环境中打开SSMS非常慢 续
    [转]Linux 下判断Server 内存是否不足
  • 原文地址:https://www.cnblogs.com/Suiyue-Li/p/11121674.html
Copyright © 2020-2023  润新知