您的位置:首页 > 其它

纪中训练 day13 线段树

2018-02-06 16:33 134 查看
目录

例题
☞jzoj1959 最大值☜
大意
数据范围

思路

代码

☞jzoj1960最大值2☜
大意
数据范围

思路

代码

例题

☞jzoj1959 最大值☜

大意

一个长度为n的序列,m次操作,两种情况分别为

1 x y:表示修改A[x]为y

2 x y:询问x到y之间的最大值

输出每次询问的答案

数据范围

1<=N<=M<=100000

思路

一个很经典的线段树练习题,直接套模板

代码

#include<bits/stdc++.h>
#define N 1000007
using namespace std;int n,m;
int a
;
int x,y,tot;
struct root{
int wz[N<<1]={0};//定义
void build(int k,int l,int r)//建造
{
if(l==r) {wz[k]=a[l];return;}
build(k<<1,l,(l+r)>>1);
build((k<<1)+1,((l+r)>>1)+1,r);
wz[k]=max(wz[k<<1],wz[k<<1|1]);//它的最大值等于它两个儿子的最大值
}
void data(int k,int l,int r,int po,int val)//修改
{
if(l==r) {wz[k]=val;return;}//只有一个了,那么直接修改
int mid=(l+r)>>1;
if(po<=mid) data(k<<1,l,mid,po,val);//左区间
else data(k<<1|1,mid+1,r,po,val);//右区间
wz[k]=max(wz[k<<1],wz[k<<1|1]);//求最大值
}
int qmax(int k,int l,int r,int ql,int qr)//在l到r之间找ql-qr的元素,k表示当前是第几个
{
if(ql<=l&&r<=qr) return wz[k];//完全包含直接返回
int mid=(l+r)>>1,ret=0;
if(ql<=mid) ret=max(ret,qmax(k<<1,l,mid,ql,qr));//访问左区间
if(mid+1<=qr) ret=max(ret,qmax(k<<1|1,mid+1,r,ql,qr));//访问右区间
return ret;//返回
}
}tree;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);//输入
tree.build(1,1,n);//建造
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&tot,&x,&y);
if(tot==1)
tree.data(1,1,n,x,y);//修改
else
printf("%d\n",tree.qmax(1,1,n,x,y));//输出
}
}


☞jzoj1960最大值2☜

大意

和上题基本一致,不过这次是区间修改

数据范围

1<=N<=M<=100000

思路

利用懒惰标记,在每次查找的时候顺便下达命令。

代码

#include<bits/stdc++.h>
#define N 1000007
#define lson k<<1
#define rson k<<1|1
using namespace std;int n,m;
long long a
;
int x,y,tot;long long z;
long long max(long long x,long long y){return x>y?x:y;}
struct ST{
long long wz[N<<2]={0},add[N<<2]={0};
void down(int k,int l,int r)//下达命令
{
if(!add[k]) return;
if(l!=r)
{add[lson]+=add[k];add[rson]+=add[k];}
wz[k]+=add[k];add[k]=0;return ;
}
void build(int k,int l,int r)//建造
{
if(l==r) {wz[k]=a[l];return;}
build(lson,l,(l+r)>>1);
build((lson)+1,((l+r)>>1)+1,r);
wz[k]=max(wz[lson],wz[rson]);
}
void change(int k,int l,int r,int ql,int qr,long long c)//改变一个区间的值
{
down(k,l,r);
if(ql<=l&&r<=qr) {add[k]+=c;return;}
int mid=(l+r)>>1;
if(ql<=mid) change(lson,l,mid,ql,qr,c);
if(qr>=mid+1) change(rson,mid+1,r,ql,qr,c);
down(lson,l,mid);down(rson,mid+1,r);
wz[k]=max(wz[lson],wz[rson]);
}
long long qmax(int k,int l,int r,int ql,int qr)//查找一个区间的最大值
{
down(k,l,r);
if(ql<=l&&r<=qr) return wz[k];
int mid=(l+r)>>1;long long ret=-214748364;
if(ql<=mid) ret=max(ret,qmax(lson,l,mid,ql,qr));
if(mid+1<=qr) ret=max(ret,qmax(rson,mid+1,r,ql,qr));
return ret;
}
}tree;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
tree.build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&tot,&x,&y);//输入
if(tot==1)
{scanf("%lld",&z);tree.change(1,1,n,x,y,z);}//修改
else
printf("%lld\n",tree.qmax(1,1,n,x,y));//输出
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: