线段树进阶练习专题
小白逛公园
题目大意:
求一段区间里最大子段和
思路:
有空补(
code:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=500100;
int m,n;
int a[MAXN];
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
struct node{
int l,r;
long long sum;//区间和
long long maxl,maxr;//最大前缀和and最大后缀和
long long maxn;//最大子段和
node()
{
l=r=0;
sum=maxl=maxr=maxn=0;
}
}z[MAXN*4];
node operator+(const node &l,const node &r)
{
node res;
res.l=l.l;res.r=r.r;
res.sum=l.sum+r.sum;
res.maxl=max(l.maxl,l.sum+r.maxl);
res.maxr=max(r.maxr,r.sum+l.maxr);
res.maxn=max(max(l.maxn,r.maxn),l.maxr+r.maxl);
return res;
}
void build(int l,int r,int rt)
{
if(l==r){
z[rt].l=z[rt].r=l;
z[rt].sum=a[l];
z[rt].maxl=z[rt].maxr=z[rt].maxn=a[l];//子段中必须有元素
// cout<<z[rt].maxr<<endl;
return;
}
int mid=(l+r)>>1;
// cout<<mid<<endl;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
void update(int l,int r,int rt,int p,int v)//单点修
{
if(l==r){
z[rt].sum=z[rt].maxl=z[rt].maxn=z[rt].maxr=v;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(l,mid,rt<<1,p,v);
else if(mid<p) update(mid+1,r,rt<<1|1,p,v);
z[rt]=z[rt<<1]+z[rt<<1|1];
}
node query(int l,int r,int rt,int nowl,int nowr)
{
if(l>=nowl&&r<=nowr){
return z[rt];
}
int mid=(l+r)>>1;
if(mid>=nowl){
if(mid<nowr) return query(l,mid,rt<<1,nowl,nowr)+query(mid+1,r,rt<<1|1,nowl,nowr);
else return query(l,mid,rt<<1,nowl,nowr);
}
else return query(mid+1,r,rt<<1|1,nowl,nowr);
}
int main()
{
//cin>>n>>m;
n=read();m=read();
for(int i=1;i<=n;i++)
{
//cin>>a[i];
a[i]=read();
}
build(1,n,1);
while(m--)
{
int k,p,s;
k=read();p=read();s=read();
if(k==1)//选择
{
if(p>s)swap(p,s);
cout<<query(1,n,1,p,s).maxn<<endl;
}
else//单点修
update(1,n,1,p,s);
}
return 0;
}
方差
题目大意:
求一段区间内的数的平均数和方差
思路:
1.求平均数
维护区间和,最后查询求一下平均数
2.求方差(没空写就从洛谷找了篇题解里的)
把方差公式展开
所以我们还需要维护区间平方和
这是下放标记
code:
调出来了再放(