给你一个666

题面:

定义一个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) 。
T给出了两个操作数a和b。以及一个数列 x1,x2,x3 ... xn ,假设a@b的结果(c,d),T非常关心数列在区间 [ min(c,d)*min(a,b) ,max(c,d)*max(a,b) ]上的最小值和最大值,T认为上述区间上的最大值和最小值可以代表666的程度,所以每组操作数都要计算出这两个最值。

坑点:

若左边界越界则取1,若右边界越界则取n。

if (l>n||l<=0) l=1;

if (r>n||r<=0) r=n;

思路:

分离时用%或/8,再用RMQ求最大最小值

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 const int N=100100;
 5 int a[N];
 6 int f1[N][20];
 7 int f2[N][20];
 8  
 9 int n,m,q,l,r,c,d,x,y;
10  
11 int min1(int l, int r) {
12     int k =log(double(r - l + 1)) / log(2.0);
13     return min(f1[l][k], f1[r - (1 << k) + 1][k]);
14 }
15  
16 int max1(int l, int r) {
17     int k =log(double(r - l + 1)) / log(2.0);
18     return max(f2[l][k], f2[r - (1 << k) + 1][k]);
19 }
20  
21 int main()
22 {
23     scanf("%d%d",&n,&q);
24     for (int i=1; i<=n; i++)
25     {
26         scanf("%d",&a[i]);
27         f1[i][0] = a[i];
28         f2[i][0] = a[i];
29     }
30     m=int(log(n*1.0)/log(2.0));
31     for (int i = 1; i <= m; i++)
32     {
33         for (int j = 1; j + (1 << i) - 1 <= n; j++)
34         {
35             f1[j][i] = min(f1[j][i - 1], f1[j + (1 << (i - 1))][i - 1]);
36             f2[j][i] = max(f2[j][i - 1], f2[j + (1 << (i - 1))][i - 1]);
37         }
38     }
39     while (q--)
40     {
41         scanf("%d%d",&x,&y);
42         c = (x/8)*(y%8);
43         d = (x%8)*(y/8);
44         l =min(c, d)*min(x, y);
45         r =max(c,d)*max(x, y);
46         if (l>n||l<=0) l=1;
47         if (r>n||r<=0) r=n;
48         printf("%d %d\n", max1(l, r), min1(l, r));
49     }
50 }
View Code

猜你喜欢

转载自www.cnblogs.com/Accpted/p/11185434.html