# 题目大意给你 n n n 个数 a 1 , . . . , a n a_1, ..., a_n a 1 , . . . , a n ,找到满足 j − i = a i + a j ( i < j ) j-i = a_i + a_j~(i < j) j − i = a i + a j ( i < j ) 的 ( i , j ) (i,j) ( i , j ) 的个数
# 数据范围1 ≤ n ≤ 2 × 1 0 5 1 \le n \le 2 \times 10^5 1 ≤ n ≤ 2 × 1 0 5 # 题解变换原式为 a i + i = j − a j a_i+i = j - a_j a i + i = j − a j ,维护一个 map<int, int> 记录已经有的 a i + i a_i + i a i + i ,对于每次新的 j j j ,累加即可
C++ 1 2 3 4 5 6 7 void solve () { cin >> n, a = vector <int >(n + 1 ); int res = 0 ; for (int i = 1 ; i <= n; i++) cin >> a[i], res += ii[i - a[i]], ii[a[i] + i]++; cout << res << '\n' ; }
# 题目大意你将收到 n n n 份礼物,你有一个情绪值 v a l val v a l ,非负整数。每收到一份礼物,你的情绪值会发生变化,每份礼物有价值 P P P 、情绪上升度 A A A 、情绪下降度 B B B
当前礼物的 P ≥ v a l P \ge val P ≥ v a l 时,v a l + = A val += A v a l + = A 当前礼物的 P < v a l P < val P < v a l 时,v a l = m a x ( 0 , v a l − B ) val = max(0, val - B) v a l = m a x ( 0 , v a l − B ) 现在有 Q Q Q 个询问,在第 i i i 个询问中,给定一个非负整数 X X X ,请问若最初 v a l = x val = x v a l = x ,收到所有礼物之后,v a l val v a l 是多少
# 数据范围1 ≤ n ≤ 1 0 4 1 \le n \le 10^4 1 ≤ n ≤ 1 0 4 1 ≤ A i , B i , P i ≤ 500 1 \le A_i, B_i, P_i \le 500 1 ≤ A i , B i , P i ≤ 5 0 0 1 ≤ Q ≤ 5 × 1 0 5 1 \le Q \le 5 \times 10^5 1 ≤ Q ≤ 5 × 1 0 5 0 ≤ X ≤ 1 0 9 0 \le X \le 10^9 0 ≤ X ≤ 1 0 9 # 题解这是一道 D P DP D P 题,本题重要的是要发现 1 ≤ A i , B i , P i ≤ 500 1 \le A_i,B_i,P_i \le 500 1 ≤ A i , B i , P i ≤ 5 0 0 这个关键条件
如果一开始的情绪值很大,那么就会一直减 否则则会在 ≤ 1000 \le 1000 ≤ 1 0 0 0 的范围变化,为什么?如果 v a l > 500 val > 500 v a l > 5 0 0 ,那么一定会减少 如果 v a l ≤ 500 val \le 500 v a l ≤ 5 0 0 ,那么就算会增加,也不会超过 1000 1000 1 0 0 0 我们不妨对 1000 1000 1 0 0 0 以内的情况去做 D P DP D P
状态变量 :d p i , j dp_{i,j} d p i , j 代表从第 i i i 件礼物开始,开始收礼物的 v a l val v a l 是 j j j ,的最终的心情转移方程 如果 j > P i j > P_i j > P i ,代表下一步心情得减,dp_{i,j}=dp_ 如果 j ≤ P i j \le P_i j ≤ P i ,代表下一步心情得加,dp_{i,j}=dp_ 倒着 D P DP D P 然后通过前缀和维护一个 b b b 的 p r e pre p r e 数组,用二分去找,我初步给出的 v a l val v a l 从那个下标开始,会进入 1000 1000 1 0 0 0 以内,然后直接用 D P DP D P 的值
C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void solve () { cin >> n; p = vector <int >(n + 10 ), a = vector <int >(n + 10 ), b = vector <int >(n + 10 ), pre = vector <int >(n + 1 ); dp = vector<vector<int >>(n + 10 , vector <int >(1010 )); for (int i = 1 ; i <= n; i++) cin >> p[i] >> a[i] >> b[i]; for (int j = 0 ; j <= 1000 ; j++) dp[n + 1 ][j] = j; for (int i = n; i >= 1 ; i--) for (int j = 0 ; j <= 1000 ; j++) dp[i][j] = dp[i + 1 ][(j > p[i] ? max ((int )0 , j - b[i]) : j + a[i])]; for (int i = 1 ; i <= n; i++) pre[i] = pre[i - 1 ] + b[i]; cin >> q; while (q--) { cin >> x; if (x - 1000 > pre[n]) cout << x - pre[n] << '\n' ; else if (x <= 1000 ) cout << dp[1 ][x] << '\n' ; else { int idx = lower_bound (pre.begin () + 1 , pre.begin () + n + 1 , x - 1000 ) - pre.begin (); cout << dp[idx + 1 ][x - pre[idx]] << '\n' ; } } }