作业题解
A
前缀和上课讲过了,说一下
思路很简单,
分类讨论前面的数取不取,则有
那么答案就是
#include <iostream>
using namespace std;
int n, m = -1e9, a[200050], dp[200050];
int main()
{
cin >> n;
for(int i = 1;i <= n;++i)
{
cin >> a[i];
dp[i] = max(a[i], a[i] + dp[i - 1]);
m = max(m, dp[i]);
}
cout << m;
return 0;
}
B
虽然 cdcq 说这个不是讲课内容,但老崔还是出了
考虑枚举左上右下角,加上求和复杂度
前缀和优化掉
考虑上一个题的思路,把二维变成一维。
首先,在矩阵上划定一个范围:
枚举这个范围需要
将这个范围中每行的和算出来:
求每行的和需要
那么,这个范围就被抽象成了灰框内的数组。
算这个数组的最大子段和,最大的子段就对应着最大的矩阵。
这样,最大矩阵就找到了,复杂度
其实这段是从以前的题解里复制出来的
#include <iostream>
using namespace std;
int s[150][150], n, t[150], ans = -1e9;
int main()
{
cin >> n;
for(int i = 1, t;i <= n;++i)
for(int j = 1;j <= n;++j)
cin >> t, s[i][j] = s[i][j - 1] + t;
for(int i = 1;i <= n;++i)
for(int j = i;j <= n;++j)
{
for(int k = 1;k <= n;++k)
t[k] = s[k][j] - s[k][i - 1];
for(int k = 1;k <= n;++k)
t[k] = max(t[k], t[k - 1] + t[k]), ans = max(ans, t[k]);
}
cout << ans;
return 0;
}
C
上课讲了离散化,实际上有一个更简单的方法。
实际上,把
________ _____
| __ |排序| __|__
| | | |--->| | | |
把排序后每一段的长度加起来,每次减去这一段和上一段的重复部分。
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
int a[20050], b[200050], n, ans;
signed main()
{
cin >> n;
for(int i = 0;i < n;++i)
cin >> a[i] >> b[i];
sort(a, a + n);
sort(b, b + n);
for(int i = 0;i < n;++i)
{
ans += b[i] - a[i];
if(i && a[i] < b[i - 1])
ans -= b[i - 1] - a[i];
}
cout << ans;
return 0;
}
D
这个题跟之前考试那个
转化成
把
#include <iostream>
#include <unordered_map>
#define int long long
using namespace std;
int a[200001], n, c, s;unordered_map<int, int> m;
signed main()
{
cin >> n >> c;
for(int i = 0;i < n;++i)
cin >> a[i], ++m[a[i]];
for(int i = 0;i < n;++i)
s += m[a[i] - c];
cout << s;
return 0;
}
E
树上前缀和板子。
但由于异或的特殊性(逆运算是本身),
原来的
就不需要
#include <iostream>
#include <list>
#include <utility>
using namespace std;
list<pair<int, int> > edge[100050];int n, m, s[100050];bool vis[100050];
void add(int u, int v, int w) {edge[u].push_back(make_pair(w, v));}
void dfs(int x, int dep)
{
vis[x] = 1;s[x] = dep;
for(auto &i : edge[x])
if(!vis[i.second])
dfs(i.second, dep ^ i.first);
}
int main()
{
cin >> n;
for(int i = 1, u, v, w;i < n;++i)
cin >> u >> v >> w, add(u, v, w), add(v, u, w);
dfs(1, 0);cin >> m;
for(int i = 0, l, r;i < m;++i)
cin >> l >> r, cout << (s[l] ^ s[r]) << endl;
return 0;
}
F
这不就树状数组差分建树板子吗
#include <iostream>
using namespace std;
#define lbt(i) (i & -i)
int c[5000050], n, p, a[5000050], ans = 1e9;
void chg(int x, int k) {for(int i = x;i <= n;i += lbt(i)) c[i] += k;}
int ask(int x) {int ret = 0;for(int i = x;i;i -= lbt(i)) ret += c[i];return ret;}
int main()
{
cin >> n >> p;
for(int i = 1;i <= n;++i)
cin >> a[i], c[i] = a[i] - a[i - lbt(i)];
for(int i = 0, x, y, z;i < p;++i)
cin >> x >> y >> z, chg(x, z), chg(y + 1, -z);
for(int i = 1;i <= n;++i)
ans = min(ans, ask(i));
cout << ans;
return 0;
}
但是数据到
这题只有一次查询,所以考虑差分数组。
#include <iostream>
using namespace std;
int d[5000050], n, p, a[5000050], ans = 1e9;
int main()
{
cin >> n >> p;
for(int i = 1;i <= n;++i)
cin >> a[i], d[i] = a[i] - a[i - 1];
for(int i = 0, x, y, z;i < p;++i)
cin >> x >> y >> z, d[x] += z, d[y + 1] -= z;
for(int i = 1;i <= n;++i)
a[i] = a[i - 1] + d[i], ans = min(ans, a[i]);
cout << ans;
return 0;
}
这样修改就是
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具