[HDU5306] Gorgeous Sequence - 线段树区间最值操作
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDU5306] Gorgeous Sequence - 线段树区间最值操作相关的知识,希望对你有一定的参考价值。
Description
维护数列,支持区间 min 操作,询问区间 max,询问区间和。
Solution
区间最值操作入门题
对线段树每个结点维护最大值 (maxnum),最大值个数 (maxcnt),次大值 (secnum),区间和 (sum)
修改某个节点时,设操作数为 (x),若 (maxnum le x) 则退出,若 (secnum ge x) 则继续递归,若 (secnum < x < maxnum) 则修改当前结点值((sum) 减少 ((maxnum-a)maxcnt),(maxnum) 变为 (a)),同时送给该点一个 lazy tag
下传 lazy tag 时,很显然一定不会出现需要递归修改的情况,于是也可以借用修改操作来处理
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 4000005;
#define lc p*2,l,(l+r)/2
#define rc p*2+1,(l+r)/2+1,r
int min(int x,signed y)
{
return min(x,1ll*y);
}
int min(signed x,int y)
{
return min(1ll*x,y);
}
int max(int x,signed y)
{
return max(x,1ll*y);
}
int max(signed x,int y)
{
return max(1ll*x,y);
}
struct Node
{
signed maxnum,maxcnt,secnum,tag,istag;
int sum;
Node()
{
tag = 4e9;
}
Node(int t1,int t2,int t3,int t4,int t5,int t6)
{
maxnum = t1;
maxcnt = t2;
secnum = t3;
sum = t4;
tag = t5;
istag = t6;
}
void set(int x)
{
maxnum = x;
maxcnt = 1;
secnum = -1;
sum = x;
tag = 4e9;
istag = 0;
}
Node operator + (const Node &b) const
{
Node res;
res.maxnum = max(maxnum, b.maxnum);
res.maxcnt = (maxnum==res.maxnum)*maxcnt + (b.maxnum==res.maxnum)*b.maxcnt;
// 次小值计算一开始写错了
if(res.maxnum == maxnum) res.secnum = secnum;
else res.secnum = maxnum;
if(res.maxnum == b.maxnum) res.secnum = max(res.secnum, b.secnum);
else res.secnum = max(res.secnum, b.maxnum);
res.sum = sum + b.sum;
res.tag = 4e9;
res.istag = 0;
return res;
}
} node[N];
Node NULLNODE = {-1,0,-1,0,4e9,0};
int n,m,a[N],t1,t2,t3,t4;
void build(int p,int l,int r)
{
if(l==r)
{
node[p].set(a[l]);
}
else
{
build(lc);
build(rc);
node[p]=node[p*2]+node[p*2+1];
}
}
void beat(int p,int l,int r,int x)
{
if(node[p].maxnum > x)
{
node[p].sum -= (node[p].maxnum - x)*node[p].maxcnt;
node[p].maxnum = x;
}
node[p].tag = min(node[p].tag, x);
node[p].istag = 1;
}
void pushdown(int p,int l,int r)
{
if(node[p].istag)
{
int t=node[p].tag;
beat(lc,t);
beat(rc,t);
node[p].tag = 4e9;
node[p].istag = 0;
}
}
void modify(int p,int l,int r,int ql,int qr,int x)
{
if(l>qr || r<ql) return;
if(l>=ql && r<=qr)
{
if(node[p].secnum >= x)
{
pushdown(p,l,r);
modify(lc,ql,qr,x);
modify(rc,ql,qr,x);
node[p] = node[p*2]+node[p*2+1];
}
else
{
beat(p,l,r,x);
}
}
else
{
pushdown(p,l,r);
modify(lc,ql,qr,x);
modify(rc,ql,qr,x);
node[p] = node[p*2]+node[p*2+1];
}
}
Node query(int p,int l,int r,int ql,int qr)
{
if(l>qr || r<ql) return NULLNODE;
if(l>=ql && r<=qr) return node[p];
pushdown(p,l,r);
return query(lc,ql,qr) + query(rc,ql,qr);
}
int read()
{
int x=0,f=1;
char ch=getchar();
for(; ch<‘0‘||ch>‘9‘; ch=getchar())if(ch==‘-‘)f=-1;
for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar())x=x*10+ch-‘0‘;
return x*f;
}
void read(int &x)
{
x=read();
}
void write(int x)
{
printf("%lld
",x);
}
void solve()
{
ios::sync_with_stdio(false);
read(n);
read(m);
for(int i=1; i<=n; i++) read(a[i]);
build(1,1,n);
for(int i=1; i<=m; i++)
{
read(t1);
read(t2);
read(t3);
if(t1==0)
{
read(t4);
modify(1,1,n,t2,t3,t4);
}
if(t1==1)
{
write(query(1,1,n,t2,t3).maxnum);
}
if(t1==2)
{
write(query(1,1,n,t2,t3).sum);
}
}
}
signed main()
{
int t;
read(t);
while(t--)
{
solve();
}
}
以上是关于[HDU5306] Gorgeous Sequence - 线段树区间最值操作的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5306 Gorgeous Sequence[线段树区间最值操作]