- Atcoder训练
- Enough Array
高质量题,建议两个星期后重新去做,滑动窗口题,找连续子串的和大于k的数
我一开始就直接想前缀和去做,但是没有考虑清楚连续的关系,只要到一个状态满足大于它的状态全部都满足
然后关键的地方是每次找到以后,把最先进入的状态弹出,也就是说从1——k变成2——k的子串,滑动窗口。
前缀和,加每个区间二分
- Enough Array
#include <bits/stdc++.h>
#define Fst first
#define Snd second
#define MP make_pair
#define ll long long
#define PII pair<int,int>
#define PIL pair<int,ll>
#define PLI pair<ll,int>
#define PLL pair<ll,ll>
#define PDD pair<double,double>
using namespace std;
int n;
ll m;
ll a[100010],pre[100010];
int main()
{
scanf("%d%lld",&n,&m);
for (int i=0;i<n;i++) scanf("%lld",&a[i]),pre[i+1]=pre[i]+a[i];
ll res=0;
for (int i=0;i<n;i++)
{
int l=0,r=n-i;
while (l<r)
{
int mid=(l+r)>>1;
if (pre[i+mid]-pre[i]>=m) r=mid;
else l=mid+1;
}
if (pre[i+l]-pre[i]>=m) res+=n-i-l+1;
}
printf("%lld\n",res); return 0;
}
滑动窗口
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ll n, K;
cin >> n >> K;
vector<ll> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
ll sum = 0;
ll ans = 0;
int left = 0;
for (int i = 0; i < n; ++i) {
sum += a[i];
while (sum >= K) {
ans += n - i;
sum -= a[left];
left++;
}
}
cout << ans << endl;
return 0;
}
- 动态规划专题
- 花店橱窗
一开始我用dfs做,我觉得数据不大可以试试,但是超时了,只能去用dp去写
看了别人代码才知道怎么转移,难点在于怎么从上一层转移到下一层,且不能重复走同一个m
- 花店橱窗
动态规划的边界条件:在初始化动态规划表dp时,我们只初始化了前i种花放在前j个花瓶中的状态,
即dp[0][j] = 0,这表示没有花时的美观程度为0。随着循环的进行,我们逐步填充dp[i][j],
其中i表示当前考虑的花的编号,j表示当前考虑的花瓶的编号。
状态转移:在状态转移过程中,我们考虑的是当前第i种花可以放在第j个花瓶中,同时确保第i种花不会放在比它编号小的花瓶中。
这是因为我们在更新dp[i][j]时,总是从dp[i][j-1]开始,即第i种花不放在第j个花瓶中,
然后检查是否将第i种花放在第j个花瓶中比放在第j-1个花瓶中更好(即dp[i-1][j-1] + mp[i][j]是否大于dp[i][j-1])。
这样,我们保证了每种花都至少被放置了一次,并且是按照编号顺序放置的。
路径记录:通过path数组记录了到达每个状态时的选择路径。
在回溯路径时,我们从dp[n][m]开始,
通过比较path[i][j]和j-1的值来确定是直接放置第i种花在第j个花瓶中,还是跳过当前花瓶,继续考虑下一个
#include <bits/stdc++.h>
using namespace std;
int n, m;
int mp[101][101];
int dp[101][101];
int path[101][101]; // 记录路径
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> mp[i][j];
}
}
// 初始化
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j] = INT_MIN;
}
}
for (int j = 0; j <= m; j++) {
dp[0][j] = 0;
}
// 动态规划
for (int i = 1; i <= n; i++) {
for (int j = i; j <= m; j++) {
dp[i][j] = dp[i][j-1]; // 不放第i种花在第j个花瓶中
if (dp[i-1][j-1] + mp[i][j] > dp[i][j]) {
dp[i][j] = dp[i-1][j-1] + mp[i][j];
path[i][j] = j; // 记录路径
}
}
}
// 输出最大美观程度
cout << dp[n][m] << '\n';
// 回溯路径
vector<int> result(n + 1);
int i = n, j = m;
while (i > 0 && j > 0) {
if (path[i][j] == j) {
result[i] = j;
i--;
j--;
} else {
j--;
}
}
// 输出每种花应该摆放的花瓶编号
for (int i = 1; i <= n; i++) {
cout << result[i] << ' ';
}
cout << '\n';
return 0;
}
标签:7.29,花瓶,int,ll,ACM,101,日记,dp,define
From: https://www.cnblogs.com/dontian/p/18330928