题面:
定义一个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 }