線段樹求區間最大值+區間更新+區間求和+lazy標記
阿新 • • 發佈:2019-02-05
馬上就省賽了,線段樹還缺個求區間最大值的板子,百度,Google全都是一個板子,而且還沒有lazy標記,樸素更新,好氣啊
區間最小值也同理
lazy的我只能自己寫
藍瘦香菇
code:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<string>
#include <set>
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
const int eps=1e-8;
const int maxn=30010;//須填寫
const int inf=0x3f3f3f3f;
int n,m;
struct node//定義結構體儲存線段樹
{
int l;
int r;
ll ma;
ll sum;
ll mark;
}s[300000];
void pushup(int k)//求和與最大值
{
s[k].sum=s[k<<1].sum+s[(k<<1)+1].sum;
s[k].ma=max(s[k<<1 ].ma,s[(k<<1)+1].ma);
}
void pushdown(int k,int d)//標記下移
{
if(s[k].mark)
{
s[k<<1].mark+=s[k].mark;
s[(k<<1)+1].mark+=s[k].mark;
s[k<<1].sum+=s[k].mark*(d-(d>>1));
//s[k<<1].ma+=s[k].mark;
s[(k<<1)+1].sum+=s[k].mark*(d>>1 );
//s[(k<<1)+1].ma+=s[k].mark;
s[k].mark=0;
}
}
void init(int l,int r,int k)
{
s[k].l=l;
s[k].r=r;
s[k].mark=0;
s[k].ma=0;
if(l==r)
{
scanf("%lld",&s[k].sum);
s[k].ma=s[k].sum;
//cout<<"輸入成功"<<endl;
return ;
}
int mid=(l+r)/2;
init(l,mid,k<<1);
init(mid+1,r,(k<<1)+1);
pushup(k);
}
ll query(int l,int r,int k)
{
if(l<=s[k].l&&r>=s[k].r)
{
return s[k].sum;
}
pushdown(k,s[k].r-s[k].l+1);
int mid=(s[k].l+s[k].r)/2;
long long res=0;
if(l<=mid) res+=query(l,r,(k<<1));
if(r>mid) res+=query(l,r,(k<<1)+1);
return res;
}
ll queryma(int l,int r,int k)//查詢最大值
{
if(l<=s[k].l&&r>=s[k].r)
{
return s[k].ma;
}
pushdown(k,s[k].r-s[k].l+1);
int mid=(s[k].l+s[k].r)/2;
long long resa=0;
long long resb=0;
if(l<=mid) resa=queryma(l,r,(k<<1));
if(r>mid) resb=queryma(l,r,(k<<1)+1);
return max(resa,resb);
}
void update(int l,int r,int c,int k)
{
if(l<=s[k].l&&r>=s[k].r)
{
s[k].mark+=c;
s[k].sum+=(c*(s[k].r-s[k].l+1));
s[k].ma+=c;
return ;
}
pushdown(k,s[k].r-s[k].l+1);
int mid=(s[k].l+s[k].r)/2;
if(l<=mid) update(l,r,c,k<<1);
if(r>mid) update(l,r,c,(k<<1)+1);
pushup(k);
}