洛谷P3130 haybalesCounting Haybale P 题解
题目
[USACO15DEC]haybalesCounting Haybale P
题解
最近刚刚自学了线段树这个数据结构,恰巧做到了这道线段树的模板题。其实也没有什么好多说的,接触过线段树的大犇肯定觉得很简单。这道题注意的是修改区间的值时用到了lazy思想,如果只是用朴素的修改法则会超时。
果然,用朴素的方法更新值果然TLE了。

于是,我使用了lazy数组,这样可以尽可能地减少不必要的修改(如果有不理解的小伙伴可以上网搜索线段树lazy的含义与用法),最终终于AK了。

代码
这是TLE的代码(请勿学习)
#include<iostream>
using namespace std;
int n, m;
typedef long long ll;
#define MAX 200001
ll sum[MAX << 2];
int mm[MAX << 2];
int a[MAX];
char c;
int le, ri, p;
inline void pushup(int rt)
{
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
mm[rt] = min(mm[rt << 1], mm[rt << 1 | 1]);
}
void build(int l, int r, int cur)
{
if (l == r)
{
sum[cur] = a[l];
mm[cur] = a[l];
return;
}
int mid = (l + r)>>1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
pushup(cur);
}
ll Sum(int L, int R, int l, int r, int cur)
{
if (l >= L && r <= R)
return sum[cur];
int mid = (l + r) >> 1;
ll res = 0;
if (mid >= L)
res += Sum(L, R, l, mid, cur << 1);
if (mid < R)
res += Sum(L, R, mid + 1, r, cur << 1 | 1);
return res;
}
ll Min(int L, int R, int l, int r, int cur)
{
if (l>=L&&r<=R)
return mm[cur];
int mid = (l + r) >> 1;
if (mid >= R)
return Min(L, R, l, mid, cur << 1);
else if (mid < L)
return Min(L, R, mid + 1, r, cur << 1 | 1);
return min(Min(L, R, l, mid, cur << 1), Min(L, R, mid + 1, r, cur << 1 | 1));
}
void update(int L, int R, int l, int r, int cur, int z)
{
if (l == r)
{
sum[cur] += z;
mm[cur] += z;
return;
}
int mid = (l + r) >> 1;
if (mid >= L)
update(L, R, l, mid, cur << 1, z);
if (mid < R)
update(L, R, mid + 1, r, cur << 1 | 1, z);
pushup(cur);
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, n, 1);
for (int i = 0; i < m; i++)
{
cin >> c;
if (c == 'M')
{
cin >> le >> ri;
cout << Min(le, ri, 1, n, 1) << '\n';
}
else if (c == 'S')
{
cin >> le >> ri;
cout<<Sum(le, ri, 1, n, 1)<<'\n';
}
else
{
cin >> le >> ri >> p;
update(le, ri, 1, n, 1, p);
}
}
return 0;
}
接下来是AC的(现学现码)
#include<iostream>
using namespace std;
int n, m;
typedef long long ll;
#define MAX 200001
ll sum[MAX << 2];
int mm[MAX << 2];
ll lazy[MAX << 2];
int a[MAX];
char c;
int le, ri, p;
inline void pushup(int rt)
{
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
mm[rt] = min(mm[rt << 1], mm[rt << 1 | 1]);
}
inline void pushdown(int rt, int l, int r)
{
lazy[rt << 1] += lazy[rt], lazy[rt << 1 | 1] += lazy[rt];
int mid = (l + r) / 2;
sum[rt << 1] += lazy[rt] * (mid - l + 1);
sum[rt << 1 | 1] += lazy[rt] * (r - mid);
mm[rt << 1] += lazy[rt];
mm[rt << 1 | 1] += lazy[rt];
lazy[rt] = 0;
}
void build(int l, int r, int cur)
{
if (l == r)
{
sum[cur] = a[l];
mm[cur] = a[l];
return;
}
int mid = (l + r)>>1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
pushup(cur);
}
ll Sum(int L, int R, int l, int r, int cur)
{
if (l >= L && r <= R)
return sum[cur];
if (lazy[cur])
pushdown(cur, l, r);
int mid = (l + r) >> 1;
ll res = 0;
if (mid >= L)
res += Sum(L, R, l, mid, cur << 1);
if (mid < R)
res += Sum(L, R, mid + 1, r, cur << 1 | 1);
return res;
}
ll Min(int L, int R, int l, int r, int cur)
{
if (l>=L&&r<=R)
return mm[cur];
if (lazy[cur])
pushdown(cur, l, r);
int mid = (l + r) >> 1;
if (mid >= R)
return Min(L, R, l, mid, cur << 1);
else if (mid < L)
return Min(L, R, mid + 1, r, cur << 1 | 1);
return min(Min(L, R, l, mid, cur << 1), Min(L, R, mid + 1, r, cur << 1 | 1));
}
void update(int L, int R, int l, int r, int cur, int z)
{
if (l >= L&&r <= R)
{
sum[cur] += (ll)z * (r - l + 1);
mm[cur] += z;
lazy[cur] += z;
return;
}
if (lazy[cur])
pushdown(cur, l, r);
int mid = (l + r) >> 1;
if (mid >= L)
update(L, R, l, mid, cur << 1, z);
if (mid < R)
update(L, R, mid + 1, r, cur << 1 | 1, z);
pushup(cur);
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
build(1, n, 1);
for (int i = 0; i < m; i++)
{
cin >> c;
if (c == 'M')
{
cin >> le >> ri;
cout << Min(le, ri, 1, n, 1) << '\n';
}
else if (c == 'S')
{
cin >> le >> ri;
cout<<Sum(le, ri, 1, n, 1)<<'\n';
}
else
{
cin >> le >> ri >> p;
update(le, ri, 1, n, 1, p);
}
}
return 0;
}
感觉自己还是太菜了。

浙公网安备 33010602011771号