线段树求(可整段修改区间)区间最值pascal 比如求最大值,加上正数的我会编,但是加负数的就不会了。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树求(可整段修改区间)区间最值pascal 比如求最大值,加上正数的我会编,但是加负数的就不会了。相关的知识,希望对你有一定的参考价值。

重点是给一段区间加上一个负数(求max)这么处理
pascal!

参考技术A 和加上正数完全一样。
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 比如求最大值,加上正数的我会编,但是加负数的就不会了。的主要内容,如果未能解决你的问题,请参考以下文章

poj 3264(线段树求区间最值)

HDU6447 YJJ's Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp

湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)

(线段树) 单点更新,区间查询最值

HDU6602 Longest Subarray(思维+线段树区间修改维护最值)

[HDU5306] Gorgeous Sequence - 线段树区间最值操作