您的位置:首页 > 其它

线段树(单点修改,区间查询)

2017-08-04 16:16 716 查看
/*
* 线段树模板
* 单点修改,区间查询
*/
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MAXN=1e5+5;//
const int INF=0x3f3f3f3f;//根据是否超long long修改
int a[MAXN];

//线段树节点结构体
struct Node{
int left,right;//左右边界
int mi,ma;//最小值 最大值
LL sum;//和
}tree[MAXN*4];//空间开四倍

//向上更新
void PushUp(int rt){
tree[rt].mi=min(tree[rt<<1].mi,tree[rt<<1|1].mi);
tree[rt].ma=max(tree[rt<<1].ma,tree[rt<<1|1].ma);
tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}

//建立函数
void Build(int rt,int L,int R){
tree[rt].left=L;tree[rt].right=R;
if(L==R) {tree[rt].sum=tree[rt].mi=tree[rt].ma=a[L]; return;}
int mid=(tree[rt].left+tree[rt].right)>>1;
Build(rt<<1,L,mid);//只有Build时LR才会变
Build(rt<<1|1,mid+1,R);
PushUp(rt);
}

LL QuerySum(int rt,int L,int R){
if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].sum;//贡献为tree[rt].sum
int mid=(tree[rt].left+tree[rt].right)>>1;
LL res=0;
if(L<=mid) res+=QuerySum(rt<<1,L,R);
if(R>mid)  res+=QuerySum(rt<<1|1,L,R);
return res;
}

int QueryMin(int rt,int L,int R){
if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].mi;
int mid=(tree[rt].left+tree[rt].right)>>1;
int res=INF;
if(L<=mid) res=min(res,QueryMin(rt<<1,L,R));
if(R>mid)  res=min(res,QueryMin(rt<<1|1,L,R));
return  res;
}

int QueryMax(int rt,int L,int R){
if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].ma;//完全包含才产生贡献
int mid=(tree[rt].left+tree[rt].right)>>1;
int res=-INF;
if(L<=mid) res=max(res,QueryMax(rt<<1,L,R));
if(R>mid)  res=max(res,QueryMax(rt<<1|1,L,R));
return  res;
}

void Update(int rt,int pos,int x){//把pos位的值改为x
if(tree[rt].left==tree[rt].right) { tree[rt].sum=tree[rt].mi=tree[rt].ma=x; return; }
int mid=(tree[rt].left+tree[rt].right)>>1;
if(pos<=mid) Update(rt<<1,pos,x);
else Update(rt<<1|1,pos,x);
PushUp(rt);
}

int main() {
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
Build(1,1,n);//建立线段树
int op,x,y;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);
if(op==1){//询问[x,y]的和
printf("%lld\n",QuerySum(1,x,y));
}else if(op==2){//询问[x,y]的最大值
printf("%d\n",QueryMax(1,x,y));
}else if(op==3){//询问[x,y]的最小值
printf("%d\n",QueryMin(1,x,y));
}else{//修改第x位的值为y
Update(1,x,y);
}
}
}
return 0;
}
/*
6 4
1 2 3 4 5 6
4
3 8
1
1 6
2
1 6
3
1 6
*/


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long LL;
const int MAXN=2e5+5;
int val[MAXN];

struct node
{
int ma,left,right;
}tree[MAXN*4];

void pushup(int rt)
{
tree[rt].ma=max(tree[lson].ma,tree[rson].ma);
}

void build(int rt,int left,int right)
{
tree[rt].left=left;
tree[rt].right=right;
if(left==right) {tree[rt].ma=val[left];return;}
int mid=(left+right)>>1;
build(lson,left,mid);
build(rson,mid+1,right);
pushup(rt);
}

int query(int rt,int left,int right)
{
if(left<=tree[rt].left&&tree[rt].right<=right) return tree[rt].ma;
int m=(tree[rt].left+tree[rt].right)>>1;
int res=0;
if(left<=m) res=max(res,query(lson,left,right));
if(right>m) res=max(res,query(rson,left,right));
return res;
}

void update(int rt,int pos,int val)
{
if(tree[rt].left==tree[rt].right) {tree[rt].ma=val;return;}
int m=(tree[rt].left+tree[rt].right)>>1;
if(pos<=m) update(lson,pos,val);
else update(rson,pos,val);
pushup(rt);
}

int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;++i)
scanf("%d",&val[i]);
build(1,1,n);
for(int i=1;i<=m;++i)
{
getchar();
char op;int x,y;
scanf("%c",&op);
scanf("%d%d",&x,&y);
if(op=='Q')
{
printf("%d\n",query(1,x,y));
}else
{
update(1,x,y);
}
}
}
return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const double eps=1e-10;
const int MAXN=1e5+5;
const int MOD=1e9+7;
int a[MAXN];
int minv[MAXN*4];

void build(int l,int r,int rt)
{
if(l==r) {minv[rt]=a[l];return;}
int m=l+(r-l)/2;
build(l,m,rt*2);
build(m+1,r,rt*2+1);
minv[rt]=min(minv[rt*2],minv[rt*2+1]);
}

int query(int o,int L,int R,int ql,int qr)
{
int M=L+(R-L)/2,ans=INF;
if(ql<=L&&R<=qr) return minv[o];//当前结点完全包含在查询区间内
if(ql<=M) ans=min(ans,query(o*2,L,M,ql,qr));//往左走
if(M<qr) ans=min(ans,query(o*2+1,M+1,R,ql,qr));//往右走
return ans;
}

void update(int o,int L,int R,int p,int v)//修改A[p]=v
{
int M=L+(R-L)/2;
if(L==R) minv[o]=v;//叶结点,直接更新minv
else
{
if(p<=M) update(o*2,L,M,p,v);
else update(o*2+1,M+1,R,p,v);
minv[o]=min(minv[o*2],minv[o*2+1]);
}
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
}
build(1,n,1);
int q;
scanf("%d",&q);
int op,x,y;
for(int i=1;i<=q;++i)
{
cin>>op>>x>>y;
if(op==1)
{
update(1,1,n,x,y);
}else if(op==2)
{
cout<<query(1,1,n,x,y)<<endl;
}
}
}
return 0;
}
/*
10
10
1 2 3 4 5 6 7 8 9 10
100
1 1 2
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: