A election
定数:普及+,普及-,普及-,无,总计普及。
(思维,实现,算法,数据结构,总计)
双指针,每一次只会打死最左的和最右的,计算是死左边还是死右边即可。
\(O(N \log N) - O(1)\)。
code
#include <bits/stdc++.h>
using namespace std;struct node {int x, id;
}arr[1000010];int n, xx[1000010];int lrmid(int x, int y) {int l = arr[x].x, r = arr[y].x, ans = 0;for(; l <= r; ) {int mid = (l + r) >> 1;//cout << mid << ' ' << mid - arr[x].x << ' ' << arr[y].x - mid << '\n';if((mid - arr[x].x) > (arr[y].x - mid)) {ans = mid, r = mid - 1;}else {l = mid + 1;}}return ans;
}int main() {freopen("election.in", "r", stdin);freopen("election.out", "w", stdout);cin >> n;for(int i = 1; i <= n; i++) {cin >> arr[i].x;arr[i].id = i;}sort(arr + 1, arr + n + 1, [](node a, node b) {return a.x < b.x;});for(int i = 1; i <= n; i++) {xx[i] = arr[i].x;}int i = 1, j = n;for(; i < j; ) {int a = lrmid(i, j);int tmp = lower_bound(xx + i, xx + j + 1, a) - xx;//cout << i << ' ' << j << ' ' << arr[i].id << ' ' << arr[j].id << ' ' << a << ' ' << tmp << '\n';if((tmp - i) >= j - tmp + 1) {j--;}else {i++;}}cout << arr[i].id << '\n';return 0;
}
B chaos
定数:提高,普及+,无,无,总计提高。
死因:现象看到了,本质没看到。
如下:
1 2 3 4 5 [k = n - 1]
1 5 4 3 2 [k += 3]
1 3 4 5 2 [k += 2]
如此以往......
有一些操作不会进行。一样是正确的。
\(O(N) - O(N)\)。
code
#include <bits/stdc++.h>
#define int long long
using namespace std;int n, k, pos[100010], arr[100010];signed main() {freopen("chaos.in", "r", stdin);freopen("chaos.out", "w", stdout);cin >> n >> k;k -= n - 1;pos[1] = 1;for(int i = 2, l = 2, r = n, rv = 0; i <= n; i++) {if(k >= n - i) {k -= n - i;rv ^= 1;}if(rv) {pos[i] = r;r--;}else {pos[i] = l;l++;}}for(int i = 1; i <= n; i++) {arr[pos[i]] = i;}for(int i = 1; i <= n; i++) {cout << arr[i] << ' ';}cout << '\n';return 0;
}
C defend
定数:提高,普及+,普及+,无,总计提高。
死因:没有想到优化。
定义 \(dp_{x, lst}\) 为最后一个为 \(x\),上一个为 \(lst\) 时至多能搞到几个人。
发现很难转移,于是引入一个辅助数组 \(dash\):
\(dash_{x, k}\) 表示当前为 \(x\),当前与上一个的 \(\operatorname{and}\) 的第 \(k\) 为固定为 \(1\) 时至多能搞到几个人。
然后就可以用 \(dash\) 优化 \(dp\) 了。
点击查看代码
#include <bits/stdc++.h>
using namespace std;int n, arr[2020], ans, dp[2020][2020], cnt[2020][110]; // dash is counted from the third number... or not?int main() {freopen("defend.in", "r", stdin);freopen("defend.out", "w", stdout);cin >> n;for(int i = 1; i <= n; i++) {cin >> arr[i];}arr[0] = arr[n + 1] = INT_MAX;//cout << DFS(0, 0) - 2 << '\n';for(int i = 1; i <= n; i++) {dp[i][0] = 1;for(int j = 31; j >= 0; j--) {cnt[i][j] = 1;}}for(int i = 1; i <= n; i++) {for(int j = 0; j < i; j++) {if(!j) {ans = max(ans, dp[i][j]);for(int k = 31; k >= 0; k--) {if((arr[j] >> k) & 1) {cnt[i][k] = max(cnt[i][k], dp[i][j]); // Update dash}}continue;}int x = (arr[i] & arr[j]);if(x) {dp[i][j] = 1;for(int k = 31; k >= 0; k--) {if((x >> k) & 1) {dp[i][j] = max(dp[i][j], cnt[j][k] + 1); // If there can be a dash}}for(int k = 31; k >= 0; k--) {if((arr[j] >> k) & 1) {cnt[i][k] = max(cnt[i][k], dp[i][j]); // Update dash}}ans = max(ans, dp[i][j]);}//cout << dp[i][j] << ' ';}//cout << '\n';}cout << max(min(n, 2), ans) << '\n';return 0;
}
D standin
定数:提高-,普及+,提高,无,总计提高-。
死因:没有输出 -1
。
一开始我想枚举宽带,后来发现不用,具体见下图:
可以看到,直接按照宽带大小,从小到大转移即可。
\(O(N2^M) - O(2^M)\)。
点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;struct node {int x, k, mask;
}arr[110];int dp[1 << 20], n, m, b, c, t, ans = LLONG_MAX;signed main() {freopen("standin.in", "r", stdin);freopen("standin.out", "w", stdout);cin >> n >> m >> b;for(int i = 1; i <= n; i++) {for(cin >> arr[i].x >> arr[i].k >> c; c--; ) {cin >> t;arr[i].mask |= (1 << (t - 1));}}sort(arr + 1, arr + n + 1, [](node a, node b) {return a.k < b.k;});memset(dp, 0x3f, sizeof(dp));dp[0] = 0;for(int i = 1; i <= n; i++) {for(int j = (1 << m) - 1; j >= 0; j--) {dp[j | arr[i].mask] = min(dp[j | arr[i].mask], dp[j] + arr[i].x);}if(dp[(1 << m) - 1] != 0x3f3f3f3f3f3f3f3f) {ans = min(ans, dp[(1 << m) - 1] + arr[i].k * b);}}cout << (ans == LLONG_MAX? -1 : ans) << '\n';return 0;
}