目录
第一次通过版:
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
#define PII pair<int,int>
#define int long long
//当前节点存的懒标记是给下面用的
//spread就是给下面用的时候
//我们或许对当前最大值maxa及时的加或减了
//但是没有对maxb做操作,或者说 **某个子区间的maxb可能就没有被更新过**
//2024/4/30
//spread -> push_down
//这里保留的是向下更新前这期间的 历史最大的 标记
//
//之前“最值”的做法是错误的,懒标记频繁更新,可能就改不到最大懒标记了。 乱写,
//
//然后就是min的操作了
//不想一次改到底
//能做到改maxa时就可以停了。
//后续的maxa大于父maxa的就是要调整的
//调整多少呢?我们可以给个懒标记3
//2024/5/1
//2操作时,不过确实有多个最大值就错了
//你的老二可能比我的牢大大
//t3更新的判断有误。可能当前又变了,子节点maxa没变过。
//懂了,其实改,肯定是改大的那个;!!!我们已经递归到只改一个的时候啦!!!
//而且次大值小于修改值,即最大值仍是最大值!
//原来最大值的懒标记要分开,是为了更新maxb 。看了良久才看出来
//所以不是最大值(取min操作没取到的)也要统计maxb,所以普通懒标记也需要记录一个本次的最大 。
//区间加u1没有及时更新 maxt1 maxt3
//
const int maxn = 5e5 + 5;
const int minv = -5e18;
//int MOD = LLONG_MAX;
class ST//segment tree
{
struct node
{
ll val;//区间和
ll maxa;//区间最大值
ll seca;//区间次大值
ll maxb;//区间历史最大值
ll maxn;//最大值数目 用于最大值修改
int t1;//加懒标记
int maxt1;//不是最大值也要统计maxb,也需要最大懒标记
int t2;//乘懒标记
int t3;//最大值专属懒标记 VIP
int maxt3;//期间最大加懒标记
node(int v = 0) :val(v), maxa(0), seca(-2e9), maxb(0), maxn(1),
t1(0), maxt1(0), t2(1), t3(0), maxt3(0)
{}
};
int n = a.size();
vector<ll>a;
vector<node>d;
void build_tree(int i, int l, int r)
{
if (l == r)
{
d[i].val = d[i].maxa = d[i].maxb = a[l];
return;
}
int mid = l + (r - l) / 2;
build_tree(i * 2, l, mid);
build_tree(i * 2 + 1, mid + 1, r);
push_up(i);
}
void push_up(int i)
{
d[i].val = (d[i * 2].val + d[i * 2 + 1].val);
d[i].maxa = max(d[i * 2].maxa, d[i * 2 + 1].maxa);
d[i].maxb = max(d[i * 2].maxb, d[i * 2 + 1].maxb);
//不过确实有多个最大值就错了
if (d[i * 2].maxa == d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].seca,d[i*2+1].seca);
d[i].maxn = d[i * 2].maxn + d[i * 2 + 1].maxn;
}
else if (d[i * 2].maxa > d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i*2].seca,d[i * 2 + 1].maxa);
d[i].maxn = d[i * 2].maxn;
}
else// if (d[i * 2].maxa < d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].maxa, d[i * 2 + 1].seca);
d[i].maxn = d[i * 2 + 1].maxn;
}
}
void change(int i, int l, int r, int t1, int maxt1,int t2,int t3, int maxt3)
{
auto& self = d[i];
//self.val = self.val * t2;
//self.maxa = self.maxa * t2;
//self.seca = self.seca * t2;
//self.t1 *= t2;
//self.t2 *= t2;
self.val += t1 * (r - l + 1 - self.maxn) + t3*self.maxn;
self.maxb = max(self.maxb, self.maxa + maxt3);
self.maxa += t3;
if(self.seca != -2e9)
self.seca += t1;
self.maxt1 = max(self.maxt1, self.t1 + maxt1);
self.t1 += t1;
self.maxt3 = max(self.maxt3, self.t3 + maxt3);
self.t3 += t3;
}
void push_down(int i,int l,int r)
{
//懒惰
int t1 = d[i].t1, maxt1 = d[i].maxt1, t2 = d[i].t2, t3 = d[i].t3, maxt3 = d[i].maxt3;
auto& lchild = d[i * 2], &rchild = d[i * 2 + 1];
int maxatmp = max(lchild.maxa, rchild.maxa);
int mid = l + (r - l) / 2;
if (lchild.maxa == maxatmp)
change(i*2,l,mid,t1, maxt1, t2,t3,maxt3);
else
change(i*2,l,mid,t1, maxt1, t2,t1,maxt1);//没专属
if (rchild.maxa == maxatmp)
change(i * 2 + 1, mid + 1, r, t1, maxt1, t2, t3, maxt3);
else
change(i * 2 + 1, mid + 1, r, t1, maxt1, t2, t1, maxt1);
//复原
d[i].t1 = d[i].maxt1 = d[i].maxt3 = d[i].t3 = 0;
d[i].t2 = 1;
}
ll _getsum(int i, int l, int r, int aiml, int aimr)
{
if (l > aimr || r < aiml)return 0;
if (aiml <= l && r <= aimr)return d[i].val;
int mid = l + (r - l) / 2;
push_down(i,l,r);
return _getsum(i * 2, l, mid, aiml, aimr) + _getsum(i * 2 + 1, mid + 1, r, aiml, aimr);
}
ll _getmaxa(int i, int l, int r, int aiml, int aimr)
{
if (l > aimr || r < aiml)return LLONG_MIN;
if (aiml <= l && r <= aimr)return d[i].maxa;
int mid = l + (r - l) / 2;
push_down(i,l,r);
return max(_getmaxa(i * 2, l, mid, aiml, aimr), _getmaxa(i * 2 + 1, mid + 1, r, aiml, aimr));
}
ll _getmaxb(int i, int l, int r, int aiml, int aimr)
{
if (l > aimr || r < aiml)return LLONG_MIN;
if (aiml <= l && r <= aimr)return d[i].maxb;
int mid = l + (r - l) / 2;
push_down(i,l,r);
return max(_getmaxb(i * 2, l, mid, aiml, aimr), _getmaxb(i * 2 + 1, mid + 1, r, aiml, aimr));
}
void _update1(int i, int l, int r, int aiml, int aimr, ll val)
{
if (l > aimr || r < aiml)return;
if (aiml <= l && r <= aimr)
{
d[i].val = (d[i].val + val * (r - l + 1));
d[i].maxa = d[i].maxa + val;
d[i].maxb = max(d[i].maxb, d[i].maxa);
if(d[i].seca != -2e9)
d[i].seca += val;
d[i].t1 += val;
d[i].t3 += val;
d[i].maxt1 = max(d[i].maxt1, d[i].t1);
d[i].maxt3 = max(d[i].maxt3, d[i].t3);
return;
}
int mid = l + (r - l) / 2;
push_down(i,l,r);//因为要向下搜了,所以把当前的懒标记给下面兑现一下
_update1(i * 2, l, mid, aiml, aimr, val);
_update1(i * 2 + 1, mid + 1, r, aiml, aimr, val);
push_up(i);
}
void _update2(int i, int l, int r, int aiml, int aimr, ll val)
{
if (l > aimr || r < aiml)return;
if (aiml <= l && r <= aimr)
{
d[i].val = (d[i].val * val);
d[i].t1 = (d[i].t1 * val);
d[i].t2 = (d[i].t2 * val);
return;
}
int mid = l + (r - l) / 2;
push_down(i,l,r);
_update2(i * 2, l, mid, aiml, aimr, val);
_update2(i * 2 + 1, mid + 1, r, aiml, aimr, val);
push_up(i);
}
void _update_min(int i, int l, int r, int aiml, int aimr, ll val)
{
if (l > aimr || r < aiml || d[i].maxa <= val)return;
if (aiml <= l && r <= aimr && d[i].seca < val)
{
int k = d[i].maxa - val;
d[i].val -= d[i].maxn* k;
d[i].maxa = val;
d[i].t3 -= k;
return;
}
int mid = l + (r - l) / 2;
push_down(i, l, r);
_update_min(i * 2, l, mid, aiml, aimr, val);
_update_min(i * 2 + 1, mid + 1, r, aiml, aimr, val);
push_up(i);
}
public:
ll getsum(int l, int r)
{
return _getsum(1, 1, n, l, r);
}
ll getmaxa(int l, int r)
{
return _getmaxa(1, 1, n, l, r);
}
ll getmaxb(int l, int r)
{
return _getmaxb(1, 1, n, l, r);
}
void update1(int l, int r, ll val)
{
_update1(1, 1, n, l, r, val);//加并挂标记
}
void update2(int l, int r, ll val)
{
_update2(1, 1, n, l, r, val);//加并挂标记
}
void update_min(int l, int r, ll val)
{
_update_min(1, 1, n, l, r, val);
}
ST(vector<ll>arr)
{
a = arr;
n = a.size() - 1;
d = vector<node>(4 * n);
build_tree(1, 1, n);
}
};
//区间加完,子区间最大值也加
//交汇部分需要再比比
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
vector<int>arr(1 + n);
for (int i = 1; i <= n; i++)
cin >> arr[i];
ST demo(arr);
for (int i = 0; i < m; i++)
{
int op, l, r, val;
cin >> op >> l >> r;
switch (op)
{
case 1:
cin >> val;
demo.update1(l, r, val);
break;
case 2:
cin >> val;
demo.update_min(l, r, val);
break;
case 3:
cout << demo.getsum(l, r) << endl;
break;
case 4:
cout << demo.getmaxa(l, r) << endl;
break;
case 5:
cout << demo.getmaxb(l, r) << endl;
break;
}
}
return 0;
}
区间乘法可用版:
简单地整理了下代码,比如函数递归时,l,r可以存入节点node结构体中。递归时,相同的aiml,aimr,val,直接用类成员变量即可,第一次调用时及时修改。
(貌似在O(2)优化下这些修改并没有真正优化。)
因为最大值用了单独的懒标记t3,所以t3需要在区间乘的时候单独乘一下。
以下代码已通过洛谷线段树2
但是线段树3还是有部分超时的,因为线段树3题目没有要求乘法,但是更新时频繁的算乘法标记和取余操作是很耗时间的。具体情况具体看待吧。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
#define PII pair<int,int>
#define int long long
const int maxn = 5e5 + 5;
const int minv = -5e18;
int MOD = 19930726;
class ST//segment tree
{
struct node
{
ll val;//区间和
ll maxa;//区间最大值
ll seca;//区间次大值
ll maxb;//区间历史最大值
ll maxn;//最大值数目 用于最大值修改
int t1;//加懒标记
int maxt1;//不是最大值也要统计maxb,也需要最大懒标记
int t2;//乘懒标记
int t3;//最大值专属懒标记 VIP
int maxt3;//期间最大加懒标记
int l, m,r;
node(int v = 0) :val(v), maxa(0), seca(-2e9), maxb(0), maxn(1),
t1(0), maxt1(0), t2(1), t3(0), maxt3(0),l(0),m(0),r(0)
{}
};
int aiml, aimr;
int val;
int n = a.size();
vector<ll>a;
vector<node>d;
void build_tree(int i, int l, int r)
{
d[i].l = l,d[i].m = l + (r - l) / 2,d[i].r = r;
if (l == r)
{
d[i].val = d[i].maxa = d[i].maxb = a[l]%MOD;
return;
}
build_tree(i * 2, l, d[i].m);
build_tree(i * 2 + 1, d[i].m + 1, r);
push_up(i);
}
void push_up(int i)
{
d[i].val = (d[i * 2].val + d[i * 2 + 1].val)%MOD;
d[i].maxa = max(d[i * 2].maxa, d[i * 2 + 1].maxa);
d[i].maxb = max(d[i * 2].maxb, d[i * 2 + 1].maxb);
//不过确实有多个最大值就错了
if (d[i * 2].maxa == d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].seca, d[i * 2 + 1].seca);
d[i].maxn = d[i * 2].maxn + d[i * 2 + 1].maxn;
}
else if (d[i * 2].maxa > d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].seca, d[i * 2 + 1].maxa);
d[i].maxn = d[i * 2].maxn;
}
else// if (d[i * 2].maxa < d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].maxa, d[i * 2 + 1].seca);
d[i].maxn = d[i * 2 + 1].maxn;
}
}
void change(int i, int t1, int maxt1, int t2, int t3, int maxt3)
{
auto& self = d[i];
self.val = self.val * t2%MOD;
self.maxa = self.maxa * t2;
self.seca = self.seca * t2;
self.t1 = self.t1*t2%MOD;
self.t3 = self.t3 * t2 % MOD;
self.t2 = self.t2*t2%MOD;
self.val = ((self.val+t1 * (d[i].r - d[i].l + 1 - self.maxn)%MOD)%MOD + t3 * self.maxn)%MOD;
self.maxb = max(self.maxb, self.maxa + maxt3);
self.maxa += t3;
if (self.seca != -2e9)
self.seca += t1;
self.maxt1 = max(self.maxt1, self.t1 + maxt1);
self.t1 = (self.t1+t1)%MOD;
self.maxt3 = max(self.maxt3, self.t3 + maxt3);
self.t3 = (self.t3+t3)%MOD;
}
void push_down(int i)
{
//懒惰
int t1 = d[i].t1, maxt1 = d[i].maxt1, t2 = d[i].t2, t3 = d[i].t3, maxt3 = d[i].maxt3;
auto& lchild = d[i * 2], & rchild = d[i * 2 + 1];
int maxatmp = max(lchild.maxa, rchild.maxa);
if (lchild.maxa == maxatmp)
change(i * 2, t1, maxt1, t2, t3, maxt3);
else
change(i * 2, t1, maxt1, t2, t1, maxt1);//没专属
if (rchild.maxa == maxatmp)
change(i * 2 + 1, t1, maxt1, t2, t3, maxt3);
else
change(i * 2 + 1, t1, maxt1, t2, t1, maxt1);
//复原
d[i].t1 = d[i].maxt1 = d[i].maxt3 = d[i].t3 = 0;
d[i].t2 = 1;
}
ll _getsum(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return 0;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].val%MOD;
push_down(i);
return (_getsum(i * 2) + _getsum(i * 2 + 1))%MOD;
}
ll _getmaxa(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return LLONG_MIN;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].maxa;
push_down(i);
return max(_getmaxa(i * 2), _getmaxa(i * 2 + 1));
}
ll _getmaxb(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return LLONG_MIN;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].maxb;
push_down(i);
return max(_getmaxb(i * 2), _getmaxb(i * 2 + 1));
}
void _update1(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return;
if (aiml <= d[i].l && d[i].r <= aimr)
{
d[i].val = (d[i].val + val * (d[i].r - d[i].l + 1))%MOD;
d[i].maxa = d[i].maxa + val;
d[i].maxb = max(d[i].maxb, d[i].maxa);
if (d[i].seca != -2e9)
d[i].seca += val;
d[i].t1 = (d[i].t1+val)%MOD;
d[i].t3 = (d[i].t3+val)%MOD;
d[i].maxt1 = max(d[i].maxt1, d[i].t1);
d[i].maxt3 = max(d[i].maxt3, d[i].t3);
return;
}
push_down(i);//因为要向下搜了,所以把当前的懒标记给下面兑现一下
_update1(i * 2);
_update1(i * 2 + 1);
push_up(i);
}
void _update2(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return;
if (aiml <= d[i].l && d[i].r <= aimr)
{
d[i].val = (d[i].val * val)%MOD;
d[i].t1 = (d[i].t1 * val)%MOD;
d[i].t3 = (d[i].t3 * val)%MOD;
d[i].t2 = (d[i].t2 * val)%MOD;
return;
}
push_down(i);
_update2(i * 2);
_update2(i * 2 + 1);
push_up(i);
}
void _update_min(int i)
{
if (d[i].l > aimr || d[i].r < aiml || d[i].maxa <= val)return;
if (aiml <= d[i].l && d[i].r <= aimr && d[i].seca < val)
{
int k = d[i].maxa - val;
d[i].val -= d[i].maxn * k;
d[i].maxa = val;
d[i].t3 -= k;
return;
}
push_down(i);
_update_min(i * 2);
_update_min(i * 2 + 1);
push_up(i);
}
public:
ll getsum(int l, int r)
{
aiml = l, aimr = r;
return _getsum(1);
}
ll getmaxa(int l, int r)
{
aiml = l, aimr = r;
return _getmaxa(1);
}
ll getmaxb(int l, int r)
{
aiml = l, aimr = r;
return _getmaxb(1);
}
void update1(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update1(1);//加并挂标记
}
void update2(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update2(1);//加并挂标记
}
void update_min(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update_min(1);
}
ST(vector<ll>arr)
{
a = arr;
n = a.size() - 1;
d = vector<node>(4 * n);
build_tree(1, 1, n);
a = {};//清空a数组
}
};
//区间加完,子区间最大值也加
//交汇部分需要再比比
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n, m, q;
cin >> n >> m >> q;
MOD = q;
vector<ll>arr(n + 1);
for (int i = 1; i <= n; i++)
cin >> arr[i];
ST demo(arr);
for (int i = 1; i <= m; i++)
{
int op;
cin >> op;
int x, y, k;
if (op == 1)
{
cin >> x >> y >> k;
demo.update2(x, y, k);
}
else if (op == 2)
{
cin >> x >> y >> k;
demo.update1(x, y, k);
}
else //if (op == 3)
{
cin >> x >> y;
cout << demo.getsum(x, y) << endl;
}
}
return 0;
}
终极版:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
#define PII pair<int,int>
#define int long long
const int maxn = 5e5 + 5;
const int minv = -5e18;
int MOD = 1e17;
class ST//segment tree
{
struct node
{
ll val;//区间和
ll maxa;//区间最大值
ll seca;//区间次大值
ll maxb;//区间历史最大值
ll maxn;//最大值数目 用于最大值修改
int t1;//加懒标记
int maxt1;//不是最大值也要统计maxb,也需要最大懒标记
int t2;//乘懒标记
int t3;//最大值专属懒标记 VIP
int maxt3;//期间最大加懒标记
int l, m, r;
node(int v = 0) :val(v), maxa(0), seca(-2e9), maxb(0), maxn(1),
t1(0), maxt1(0), t2(1), t3(0), maxt3(0), l(0), m(0), r(0)
{}
};
int aiml, aimr;
int val;
int n = a.size();
vector<ll>a;
vector<node>d;
void build_tree(int i, int l, int r)
{
d[i].l = l, d[i].m = l + (r - l) / 2, d[i].r = r;
if (l == r)
{
d[i].val = d[i].maxa = d[i].maxb = a[l] ;
return;
}
build_tree(i * 2, l, d[i].m);
build_tree(i * 2 + 1, d[i].m + 1, r);
push_up(i);
}
void push_up(int i)
{
d[i].val = (d[i * 2].val + d[i * 2 + 1].val) ;
d[i].maxa = max(d[i * 2].maxa, d[i * 2 + 1].maxa);
d[i].maxb = max(d[i * 2].maxb, d[i * 2 + 1].maxb);
//不过确实有多个最大值就错了
if (d[i * 2].maxa == d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].seca, d[i * 2 + 1].seca);
d[i].maxn = d[i * 2].maxn + d[i * 2 + 1].maxn;
}
else if (d[i * 2].maxa > d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].seca, d[i * 2 + 1].maxa);
d[i].maxn = d[i * 2].maxn;
}
else// if (d[i * 2].maxa < d[i * 2 + 1].maxa)
{
d[i].seca = max(d[i * 2].maxa, d[i * 2 + 1].seca);
d[i].maxn = d[i * 2 + 1].maxn;
}
}
void change(int i, int t1, int maxt1, int t2, int t3, int maxt3)
{
auto& self = d[i];
//self.val = self.val * t2%MOD;
//self.maxa = self.maxa * t2;
//self.seca = self.seca * t2;
//self.t1 = self.t1*t2%MOD;
//self.t3 = self.t3 * t2 % MOD;
//self.t2 = self.t2*t2%MOD;
self.val = ((self.val + t1 * (d[i].r - d[i].l + 1 - self.maxn) ) + t3 * self.maxn) ;
self.maxb = max(self.maxb, self.maxa + maxt3);
self.maxa += t3;
if (self.seca != -2e9)
self.seca += t1;
self.maxt1 = max(self.maxt1, self.t1 + maxt1);
self.t1 = (self.t1 + t1) ;
self.maxt3 = max(self.maxt3, self.t3 + maxt3);
self.t3 = (self.t3 + t3) ;
}
void push_down(int i)
{
//懒惰
int t1 = d[i].t1, maxt1 = d[i].maxt1, t2 = d[i].t2, t3 = d[i].t3, maxt3 = d[i].maxt3;
auto& lchild = d[i * 2], & rchild = d[i * 2 + 1];
int maxatmp = max(lchild.maxa, rchild.maxa);
if (lchild.maxa == maxatmp)
change(i * 2, t1, maxt1, t2, t3, maxt3);
else
change(i * 2, t1, maxt1, t2, t1, maxt1);//没专属
if (rchild.maxa == maxatmp)
change(i * 2 + 1, t1, maxt1, t2, t3, maxt3);
else
change(i * 2 + 1, t1, maxt1, t2, t1, maxt1);
//复原
d[i].t1 = d[i].maxt1 = d[i].maxt3 = d[i].t3 = 0;
d[i].t2 = 1;
}
ll _getsum(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return 0;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].val;
push_down(i);
return (_getsum(i * 2) + _getsum(i * 2 + 1)) ;
}
ll _getmaxa(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return LLONG_MIN;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].maxa;
push_down(i);
return max(_getmaxa(i * 2), _getmaxa(i * 2 + 1));
}
ll _getmaxb(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return LLONG_MIN;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].maxb;
push_down(i);
return max(_getmaxb(i * 2), _getmaxb(i * 2 + 1));
}
void _update1(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return;
if (aiml <= d[i].l && d[i].r <= aimr)
{
d[i].val = (d[i].val + val * (d[i].r - d[i].l + 1));
d[i].maxa = d[i].maxa + val;
d[i].maxb = max(d[i].maxb, d[i].maxa);
if (d[i].seca != -2e9)
d[i].seca += val;
d[i].t1 = (d[i].t1 + val);
d[i].t3 = (d[i].t3 + val);
d[i].maxt1 = max(d[i].maxt1, d[i].t1);
d[i].maxt3 = max(d[i].maxt3, d[i].t3);
return;
}
push_down(i);//因为要向下搜了,所以把当前的懒标记给下面兑现一下
_update1(i * 2);
_update1(i * 2 + 1);
push_up(i);
}
void _update2(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return;
if (aiml <= d[i].l && d[i].r <= aimr)
{
d[i].val = (d[i].val * val);
d[i].t1 = (d[i].t1 * val);
d[i].t3 = (d[i].t3 * val);
d[i].t2 = (d[i].t2 * val);
return;
}
push_down(i);
_update2(i * 2);
_update2(i * 2 + 1);
push_up(i);
}
void _update_min(int i)
{
if (d[i].l > aimr || d[i].r < aiml || d[i].maxa <= val)return;
if (aiml <= d[i].l && d[i].r <= aimr && d[i].seca < val)
{
int k = d[i].maxa - val;
d[i].val -= d[i].maxn * k;
d[i].maxa = val;
d[i].t3 -= k;
return;
}
push_down(i);
_update_min(i * 2);
_update_min(i * 2 + 1);
push_up(i);
}
public:
ll getsum(int l, int r)
{
aiml = l, aimr = r;
return _getsum(1);
}
ll getmaxa(int l, int r)
{
aiml = l, aimr = r;
return _getmaxa(1);
}
ll getmaxb(int l, int r)
{
aiml = l, aimr = r;
return _getmaxb(1);
}
void update1(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update1(1);//加并挂标记
}
void update2(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update2(1);//加并挂标记
}
void update_min(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update_min(1);
}
ST(vector<ll>arr)
{
a = arr;
n = a.size() - 1;
d = vector<node>(4 * n);
build_tree(1, 1, n);
a = {};//清空a数组
}
};
//区间加完,子区间最大值也加
//交汇部分需要再比比
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n, m;
cin >> n >> m;
vector<int>arr(1 + n);
for (int i = 1; i <= n; i++)
cin >> arr[i];
ST demo(arr);
for (int i = 0; i < m; i++)
{
int op, l, r, val;
cin >> op >> l >> r;
switch (op)
{
case 1:
cin >> val;
demo.update1(l, r, val);
break;
case 2:
cin >> val;
demo.update_min(l, r, val);
break;
case 3:
cout << demo.getsum(l, r) << endl;
break;
case 4:
cout << demo.getmaxa(l, r) << endl;
break;
case 5:
cout << demo.getmaxb(l, r) << endl;
break;
}
}
return 0;
}
# 线段树框架:
class ST//segment tree
{
struct node
{
ll val;
int l, m, r;
node(int v = 0) :val(v), l(0), m(0), r(0)
{}
};
int aiml, aimr;
int val;
int n = a.size();
vector<ll>a;
vector<node>d;
void build_tree(int i, int l, int r)
{
d[i].l = l, d[i].m = l + (r - l) / 2, d[i].r = r;
if (l == r)
{
d[i].val = a[l] ;
return;
}
build_tree(i * 2, l, d[i].m);
build_tree(i * 2 + 1, d[i].m + 1, r);
push_up(i);
}
void push_up(int i)
{
d[i].val = (d[i * 2].val + d[i * 2 + 1].val) ;
}
void push_down(int i)
{
auto& lchild = d[i * 2], & rchild = d[i * 2 + 1];
}
ll _getsum(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return 0;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].val;
//push_down(i);
return (_getsum(i * 2) + _getsum(i * 2 + 1)) ;
}
ll _getmax(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return LLONG_MIN;
if (aiml <= d[i].l && d[i].r <= aimr)return d[i].val;
//push_down(i);
return max(_getmaxa(i * 2), _getmaxa(i * 2 + 1));
}
void _update1(int i)
{
if (d[i].l > aimr || d[i].r < aiml)return;
if (aiml <= d[i].l && d[i].r <= aimr)
{
d[i].val = (d[i].val + val * (d[i].r - d[i].l + 1));
return;
}
//push_down(i);//因为要向下搜了,所以把当前的懒标记给下面兑现一下
_update1(i * 2);
_update1(i * 2 + 1);
//push_up(i);
}
public:
ll getsum(int l, int r)
{
aiml = l, aimr = r;
return _getsum(1);
}
ll getmax(int l, int r)
{
aiml = l, aimr = r;
return _getmax(1);
}
void update1(int l, int r, ll val)
{
aiml = l, aimr = r;
this->val = val;
_update1(1);//加并挂标记
}
ST(vector<ll>arr)
{
a = arr;
n = a.size() - 1;
d = vector<node>(4 * n);
build_tree(1, 1, n);
a = {};//清空a数组
}
};