Codeforces 940 区间DP单调队列优化
A
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-8; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxm = 300; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; int num[105]; int main() { int n, d; cin >> n >> d; int anser = 0; for (int i = 1; i <= n; i++) { cin >> num[i]; } if (n == 1) { cout << 0 << endl; return 0; } sort(num + 1, num + 1 + n); int now = num[n] - num[1]; int l = 1; int r = n; for (int i = n - 1; i >= 1; i--) { for (int j = 1; j <= n - i; j++) { if (num[j + i] - num[j] <= d) { cout << n - i - 1 << endl; return 0; } } } cout<<n-1<<endl; return 0; }
B
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-8; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxm = 300; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; int num[105]; int main() { ll n, k, a, b; cin >> n >> k >> a >> b; ll now = n; ll cost = 0; ll remain, aim; if (k == 1) { cost += 1LL * a * (now - 1); cout << cost << endl; return 0; } while (now != 1) { if (now < k) { cost += 1LL * a * (now - 1); break; } remain = now % k; cost += remain * a; now -= remain; aim = now / k; cost += min(1LL * a * (now - aim), 1LL * b); now = aim; } cout << cost << endl; return 0; }
C
找字典序最小的比给定字符串S大的字符串T
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-8; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxm = 300; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; int num[30]; int nextt[30]; int main() { int n, k; string a; cin >> n >> k >> a; for (int i = 0; i < n; i++) { num[a[i] - 'a'] = 1; } for (int i = 0; i <= 25; i++) { for (int j = i + 1; j <= 25; j++) { if (num[j]) { nextt[i] = j; break; } } } if (k > n) { cout << a; int aim; for (int i = 0; i <= 25; i++) { if (num[i]) { aim = i; break; } } char ch = 'a' + aim; for (int i = 1; i <= k - n; i++) { cout << ch; } cout << endl; } else { int aim; int cur; for (int i = k - 1; i >= 0; i--) { if (nextt[a[i] - 'a'] != 0) { aim = nextt[a[i] - 'a']; cur = i; break; } } for (int i = 0; i < cur; i++) { cout << a[i]; } char ch = aim + 'a'; cout << ch; for (int i = 0; i <= 25; i++) { if (num[i]) { aim = i; break; } } ch = aim + 'a'; for (int i = 1; i <= k - cur - 1; i++) { cout << ch; } cout << endl; } return 0; }
D
在01边界的时候更新答案范围即可
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-8; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxm = 300; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; int num[100005]; int minnum[100005]; int maxnum[100005]; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { scanf("%d", &num[i]); } string a; cin >> a; for (int i = 5; i <= n; i++) { int maxn = -1000000001; for (int j = 0; j <= 4; j++) { maxn = max(maxn, num[i - j]); } maxnum[i] = maxn; } for (int i = 5; i <= n; i++) { int minn = 1000000001; for (int j = 0; j <= 4; j++) { minn = min(minn, num[i - j]); } minnum[i] = minn; } int l = -1000000000; int r = 1000000000; for (int i = 4; i <= n - 1; i++) { if (a[i] == '1' && a[i - 1] == '0') { l = max(l, maxnum[i + 1] + 1); } if (a[i] == '0' && a[i - 1] == '1') { r = min(r, minnum[i + 1] - 1); } } cout << l << " " << r << endl; return 0; }
E
单调队列优化DP
可以证明全局最小值<=局部最小值 所以全部块要不是一块一块的 要不就是C块里面的
因为每一个块有两种选择 所以DP方程为dp[i]=min(dp[i-1]+num[i],dp[i-c]+pre[i]-pre[i-c]-min(num[j]) ) [i-c+1<=j<=i]
dp[i]为到第i位最少需要的代价
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #define TS printf("!!!\n") #define pb push_back #define inf 1e9 //std::ios::sync_with_stdio(false); using namespace std; //priority_queue<int,vector<int>,greater<int>> que; get min const double eps = 1.0e-10; const double EPS = 1.0e-4; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation const int MAXN = 1e5 + 5; ll num[MAXN]; int q[MAXN]; int head, tail; ll dp[MAXN]; ll pre[MAXN]; list<int> que; int main() { int n, c; cin >> n >> c; for (int i = 1; i <= n; i++) { scanf("%lld", num + i); pre[i] = pre[i - 1] + num[i]; } for (int i = 1; i <= n; i++) { dp[i] = dp[i - 1] + num[i]; while (head >= tail && i - c >= q[tail]) { tail++; } while (head >= tail && num[q[head]] > num[i]) { head--; } q[++head] = i; if (i >= c) { dp[i] = min(dp[i], dp[i - c] + pre[i] - pre[i - c] - num[q[tail]]); } } cout << dp[n] << endl; }