线段树求(可整段修改区间)区间最值pascal 比如求最大值,加上正数的我会编,但是加负数的就不会了。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树求(可整段修改区间)区间最值pascal 比如求最大值,加上正数的我会编,但是加负数的就不会了。相关的知识,希望对你有一定的参考价值。
重点是给一段区间加上一个负数(求max)这么处理
pascal!
program ysh(input,output);
var
n,i,p,q,x,y,num:longint;
Tree:array[1..400000] of longint;
function min(a,b:longint):longint;
begin
if a<b then min:=a
else min:=b;
end;
procedure Ins_Tree(p,Tl,Tr,l,r,num:longint);
var
Tmid:longint;
begin
if (Tl=l) and (Tr=r) then
begin
Tree[p]:=num;
exit;
end;
Tmid:=(Tl+Tr) div 2;
if (r<=Tmid) then
Ins_Tree(2*p,Tl,Tmid,l,r,num)
else
if (l>=Tmid) then
Ins_Tree(2*p+1,Tmid,Tr,l,r,num);
else
begin
Ins_Tree(2*p,Tl,Tmid,l,r,num);
Ins_Tree(2*p+1,Tmid,Tr,l,r,num);
end;
Tree[p]:=min(Tree[2*p],tree[2*p+1]);
end;
function GetMin(p,Tl,Tr,l,r:longint):longint;
var
Tmid:longint;
begin
if (Tl=l)and(Tr=r) then exit(tree[p]);
Tmid:=(Tl+Tr) div 2;
if (r<=Tmid) then
GetMin:=(GetMin(2*p,Tl,Tmid,l,r))
else
if (l>=Tmid) then
GetMin:=(GetMin(2*p+1,Tmid,Tr,l,r))
else
GetMin:=min(GetMin(2*p,Tl,Tmid,l,Tmid),GetMin(2*p+1,Tmid,Tr,Tmid,r));
end;
begin
readln(n,q);
fillchar(tree,sizeof(tree),0);
for i:=1 to n do
begin
read(num);
Ins_Tree(1,1,n+1,i,i+1,num);
end;
for i:=1 to q do
begin
readln(p,x,y);
if p=1 then
write(GetMin(1,1,n+1,x,y+1),' ')
else
Ins_Tree(1,1,n+1,x,x+1,y);
end;
end. 参考技术B 我认为应该和加上正数一样处理本回答被提问者采纳
[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();
}
}
以上是关于线段树求(可整段修改区间)区间最值pascal 比如求最大值,加上正数的我会编,但是加负数的就不会了。的主要内容,如果未能解决你的问题,请参考以下文章
HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp
湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)