1 条题解
-
1
题目分析
题意简述
给定一个包含 ( 且 为偶数)个整数的数组 ,数组 的元素由公式 $A[i] = (a_1 \times i \times i + a_2 \times i + a_3) \bmod 9973$ 确定,其中 ()。另外有三个数组 、 和 ,数组 和 各有 ()个元素,$S[i] = (s_1 \times i \times i + s_2 \times i + s_3) \bmod (N/2)$,$E[i] = S[i] + [(e_1 \times i \times i + e_2 \times i + e_3) \bmod (N/2)]$,其中 ()。而 $R[i] = \min\{A[S[i]], A[S[i] + 1], \cdots, A[E[i]]\}$。需要找出最小的 ,使得 。
输入
- 第一行输入测试用例的数量 。
- 对于每个测试用例,输入一行包含 个整数,分别为 、、、、、、、、、、。
输出
对于每个测试用例,输出一行,为满足 的最小的 值。
解题思路
构建线段树
为了高效地查询数组 中任意区间 的最小值,使用线段树这种数据结构。通过递归构建线段树,每个节点存储对应区间的最小值。
计算 、 和 数组
- 根据给定的公式计算数组 和 的每个元素。
- 利用线段树查询 数组中 区间的最小值,得到 数组的每个元素。
找出最大 值的最小索引
遍历 数组,找出最大值,并记录该最大值第一次出现的索引。
代码实现
#include <iostream> #include <stdio.h> using namespace std; int N, M; int a1, a2, a3, s1, s2, s3, e1, e2, e3; int xds[200002]; int mum[50005]; int S(long long int i){ long long int ans = i*i*s1 + i*s2 + s3; return (int)(ans%(N/2)); } int E(long long int i, int s){ long long int ans = i*i*e1 + i*e2 + e3; return s + (int)(ans%(N/2)); } int A(long long int i){ long long int ans = i*i*a1 + i*a2 + a3; return (int)(ans%9973); } int mn(int a, int b){ return (a<b) ? a : b; } void jxds(int start, int end, int bh){ if(start == end){ xds[bh] = A(start); return; } int mid = (start+end)/2; jxds(start, mid, 2*bh+1); jxds(mid+1, end, 2*bh+2); xds[bh] = mn(xds[2*bh+1], xds[2*bh+2]); } int cx(int cxStart, int cxEnd, int xzStart, int xzEnd, int bh){ if(cxStart == xzStart && cxEnd == xzEnd){ return xds[bh]; } int xzMid = (xzStart+xzEnd)/2; if(cxEnd <= xzMid){ return cx(cxStart, cxEnd, xzStart, xzMid, 2*bh+1); } else if(cxStart > xzMid){ return cx(cxStart, cxEnd, xzMid+1, xzEnd, 2*bh+2); } else{ int hx1 = cx(cxStart, xzMid, xzStart, xzMid, 2*bh+1); int hx2 = cx(xzMid+1, cxEnd, xzMid+1, xzEnd, 2*bh+2); return mn(hx1, hx2); } } int cx(int s, int e){ return cx(s, e, 0, N-1, 0); } int main() { int t; scanf("%d", &t); for(int ii = 0; ii < t; ii++){ scanf("%d%d%d%d%d%d%d%d%d%d%d", &N , &a1, &a2, &a3, &M ,&s1, &s2, &s3, &e1, &e2, &e3); jxds(0, N-1, 0); int mx = 0; for(int i = 0; i < M; i++){ int si = S(i); int ei = E(i, si); mum[i] = cx(si, ei); //cout << mum[i] << endl; if(mum[i] > mx) mx = mum[i]; } for(int i = 0; i < M; i++){ if(mum[i] == mx){ printf("%d\n", i); break; } } } return 0; }
代码说明
- 全局变量:
N
和M
分别存储数组 的长度和数组 、、 的长度。a1
、a2
、a3
、s1
、s2
、s3
、e1
、e2
、e3
存储输入的系数。xds
数组用于存储线段树的节点值。mum
数组用于存储 数组的元素。
- 函数功能:
S(i)
:根据公式计算 的值。E(i, s)
:根据公式计算 的值,其中s
为 的值。A(i)
:根据公式计算 的值。mn(a, b)
:返回 和 中的较小值。jxds(start, end, bh)
:递归构建线段树,start
和end
表示当前节点对应的区间,bh
表示当前节点在线段树数组中的编号。cx(cxStart, cxEnd, xzStart, xzEnd, bh)
:在线段树中查询区间 的最小值,xzStart
和xzEnd
表示当前节点对应的区间,bh
表示当前节点在线段树数组中的编号。cx(s, e)
:调用cx(cxStart, cxEnd, xzStart, xzEnd, bh)
函数查询区间 的最小值。
- 主函数流程:
- 读取测试用例的数量 。
- 对于每个测试用例:
- 读取 、、、、、、、、、、。
- 调用
jxds(0, N - 1, 0)
构建线段树。 - 遍历 从 到 ,计算 和 ,并使用线段树查询 数组中 区间的最小值,存储在
mum[i]
中,同时更新最大值mx
。 - 再次遍历 从 到 ,找到第一个满足
mum[i] == mx
的 ,输出该 值。
- 1
信息
- ID
- 342
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者