何意味是什么意思。
2026-01-11 00:05:51
发布于:广东
26阅读
0回复
0点赞
题意解析:给定一个长度为 的数组 。你需要进行 次操作,操作共有两种:
- 操作 1:给定 ,将 中 的值增加 。
- 操作 2:给定 ,求 。
你说得对,但是我不会离线,也不会线段树树状数组等复杂数据结构。
所以我只能从暴力出发,看看能不能解决。
注意到暴力有两种做法:
- 开一个前缀和数组,对于操作 1,枚举 ,将 的值增加 ,然后从头更新前缀和数组;对于操作 2,暴力查询前缀和数组即可。操作 1 ,操作 2 。
- 开一个前缀和数组,不做修改,另开一个数组额外记录下每次操作的信息。对于操作 ,直接将信息加入到操作数组内即可;对于操作 2,先查询前缀和数组,然后枚举之前的操作,看看对这个区间做了多少贡献。操作 1 ,操作 2 。
我们发现,这两种做法好像可以合并。
我们可以在第二种做法的基础上,定时清空之前的操作。具体做法就是
再开一个差分数组。对于操作 1,在差分数组的 处 , 处 ;每隔 次操作,通过差分数组 重新计算出 以及前缀和数组,并清空操作数组。这样操作 2 的时间复杂度就降为 了。
总时间复杂度就是 ,当 取 时,总时间复杂度为 。
namespace cjdst{
void solve(){
const ll B = 1750;
ll n, m;
std::cin >> n >> m;
std::vector <ll> a(n + 5), pre(n + 5), dif(n + 5);
for(int i = 1; i <= n; i++){
std::cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
struct Query{
ll left, right, k;
};
std::vector <Query> query;
for(int _ = 1; _ <= m; _++){
int tmp;
std::cin >> tmp;
if(tmp == 1){
ll l, r, k;
std::cin >> l >> r >> k;
query.push_back({l, r, k});
dif[l] += k, dif[r + 1] -= k;
}else{
ll l, r;
std::cin >> l >> r;
ll ans = pre[r] - pre[l - 1];
for(auto i:query){
if(i.right < l || i.left > r) continue;
ans += i.k * (std::min(r, i.right) - std::max(l, i.left) + 1);
}
std::cout << ans << '\n';
}
if(_ % B == 0){
query.clear();
ll cur = 0;
for(int i = 1; i <= n; i++){
cur += dif[i];
a[i] += cur;
dif[i] = 0;
pre[i] = pre[i - 1] + a[i];
}
}
}
}
}
全部评论 1
6
2026-01-11 来自 江西
0










有帮助,赞一个