目录
1.天使果冻
2.dd爱旋转
3.小红取数
1.天使果冻
链接https://ac.nowcoder.com/acm/problem/219641
一开始都可以想到将数组的前x个数拿出来排降序输出第二个数即可。
但是因为询问量和数据量都较大,每次询问一次都要排序一次数组,会超时,所以应该去想更优的解法:
预处理 / 动态规划
提前将前 i 个数的次大值存入dp表中,询问时直接读取dp表即可
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;int n, t, x;
int a[N];
int dp[N];int main()
{cin >> n;for(int i = 1; i <= n; ++i)cin >> a[i];dp[2] = min(a[1], a[2]);int m = max(a[1], a[2]);for(int i = 3; i <= n; ++i){if(a[i] >= m){dp[i] = m;m = a[i];}else if(a[i] > dp[i - 1]){dp[i] = a[i];}else{dp[i] = dp[i - 1];}}cin >> t;while(t--){cin >> x;cout << dp[x] << endl;} return 0;
}
2.dd爱旋转
链接https://ac.nowcoder.com/acm/problem/221786
模拟题,直接模拟的话可以自己草拟一遍,会发现很复杂,所以正解肯定不是直接模拟,要去寻找规律:
1.顺时针旋转180° -》列对称一遍再行对称一遍
2.关于行镜像 -》如题意一样,行对称即可
因为每对称两次就会回到初始状态,因此可以模上2:
#include <iostream>using namespace std;const int N = 1010;
int n;
int g[N][N];void setRow() // ⾏对称
{for (int i = 0; i < n / 2; i++){for (int j = 0; j < n; j++){swap(g[i][j], g[n - 1 - i][j]);}}
}void setCol() // 列对称
{for (int j = 0; j < n / 2; j++){for (int i = 0; i < n; i++){swap(g[i][j], g[i][n - 1 - j]);}}
}int main()
{cin >> n;for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){cin >> g[i][j];}}int q, x;cin >> q;int row = 0, col = 0;while (q--){cin >> x;if (x == 1) row++, col++;else row++;}row %= 2; col %= 2;if (row) setRow();if (col) setCol();for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){cout << g[i][j] << " ";}cout << endl;}return 0;
}
3.小红取数
链接https://www.nowcoder.com/practice/6a7b2b6c9e3a4f56b1db9f8ca08d889b?tpId=230&tqId=38958&ru=/exam/oj
类似01背包的dp问题:
最重要的老样子还是状态表示:
dp[i][j] :从前i个中挑选,总和 % k == j时,最大总和为多少
因此就可以推出前一个状态为的 j 为 j - a[i] % k
又因为可能会出现相减之后出现负数,因此可以用加上k后再除k(经常用到)的方法
即(j - a[i] % k + k)% k(可以防止出现负数以及加k后导致的超出范围)
有了这几点,状态转移方程就非常好推了,只需要注意一下非法值的初始化即可
#include <iostream>
#define int long long
using namespace std;int n, k;
int a[1010];
int dp[1010][1010];signed main() {cin >> n >> k;for(int i = 1; i <= n; ++i)cin >> a[i];for(int i = 1; i <= k; ++i)dp[0][i] = -1;for(int i = 1; i <= n; ++i){for(int j = 0; j < k; ++j){dp[i][j] = dp[i - 1][j];if(dp[i - 1][(j - a[i] % k + k) % k] != -1)dp[i][j] = max(dp[i - 1][j], dp[i - 1][(j - a[i] % k + k) % k] + a[i]);}}if (dp[n][0] <= 0) cout << -1 << endl;else cout << dp[n][0] << endl;return 0;
}