table of Contents
Maximum interval
Interval maximum operation often uses the following methods
Line segment tree maintenance:
- Maximum interval mx mxmx
- Strictly second largest interval smx smxsmx
- Interval sum sumsum
- Maximum number of interval cnt cntcnt
- Interval value most lazy marker lazy lazylazy
To achieve the minimum interval operation, consider the interval maintained by the u node, and proceed as follows
- 当 m x ≤ x mx\leq x mx≤x . Obviously this modification will not affect the interval maintained by this node, so exit directly.
- 当 s m x < x < m x smx<x<mx smx<x<m x , obviously this modification will only affect all the maximum values in this interval, so you can directly update the interval and the maximum value of the interval according to the number of maximum values, mark the lazy mark and exit.
- 当 x < = s m x x<=smx x<=s m x cannot be updated directly, so the left and right subtrees are recursively.
For the time complexity, please directly refer to the 2016 National Training Team Paper of Teacher Ji (not very good~
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=998244353;
const int N=1000010;
// 快读
template <class T>
inline void read(T &res)
{
res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
if (bo) res = ~res + 1;
}
struct node
{
int l,r;
ll mx,smx,sum;
int cnt;
ll lazy;
}tree[N<<2];
int n,m;
ll a[N];
void pushup(int u)
{
tree[u].sum=tree[u<<1].sum+tree[u<<1|1].sum;
if(tree[u<<1].mx>tree[u<<1|1].mx)
{
tree[u].mx=tree[u<<1].mx;
tree[u].smx=max(tree[u<<1].smx,tree[u<<1|1].mx);
tree[u].cnt=tree[u<<1].cnt;
}
else if(tree[u<<1].mx<tree[u<<1|1].mx)
{
tree[u].mx=tree[u<<1|1].mx;
tree[u].smx=max(tree[u<<1|1].smx,tree[u<<1].mx);
tree[u].cnt=tree[u<<1|1].cnt;
}
else
{
tree[u].mx=tree[u<<1|1].mx;
tree[u].smx=max(tree[u<<1].smx,tree[u<<1|1].smx);
tree[u].cnt=tree[u<<1].cnt+tree[u<<1|1].cnt;
}
}
void pushlazy(int u,ll x)
{
if(tree[u].mx<=x) return;
tree[u].sum+=(x-tree[u].mx)*tree[u].cnt;
tree[u].mx=tree[u].lazy=x;
}
void pushdown(int u)
{
if(tree[u].lazy==-1) return;
pushlazy(u<<1,tree[u].lazy),pushlazy(u<<1|1,tree[u].lazy);
tree[u].lazy=-1;
}
void build(int u,int l,int r)
{
tree[u]={
l,r,0,-1,0,0,-1};
if(l==r)
{
tree[u].mx=tree[u].sum=a[l];
tree[u].cnt=1;
return;
}
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,ll x)
{
if(x>=tree[u].mx) return;
if(tree[u].l>=l&&tree[u].r<=r&&tree[u].smx<x)
{
pushlazy(u,x);
return;
}
pushdown(u);
int mid=tree[u].l+tree[u].r>>1;
if(l<=mid) modify(u<<1,l,r,x);
if(r>mid) modify(u<<1|1,l,r,x);
pushup(u);
}
ll qmax(int u,int l,int r)
{
if(tree[u].l>=l&&tree[u].r<=r) return tree[u].mx;
int mid=tree[u].r+tree[u].l>>1;
pushdown(u);
ll v=-1;
if(l<=mid) v=max(v,qmax(u<<1,l,r));
if(r>mid) v=max(v,qmax(u<<1|1,l,r));
pushup(u);
return v;
}
ll qsum(int u,int l,int r)
{
if(tree[u].l>=l&&tree[u].r<=r) return tree[u].sum;
int mid=tree[u].r+tree[u].l>>1;
pushdown(u);
ll v=0;
if(l<=mid) v+=qsum(u<<1,l,r);
if(r>mid) v+=qsum(u<<1|1,l,r);
pushup(u);
return v;
}
int main()
{
//IO;
int T=1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==0)
{
ll v;
scanf("%lld",&v);
modify(1,l,r,v);
}
else if(op==1)
printf("%lld\n",qmax(1,l,r));
else
printf("%lld\n",qsum(1,l,r));
}
}
return 0;
}