线段树各种小练习

1.对于一个整数数组,要求资持单点修改,查询区间l r中的max(ai-aj)(l<=j<i<=r)

/*
对于每个合并 
答案=左孩子的ans 右孩子的ans 右孩子的max-左孩子的min 
三者取大 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100010
#define inf 0x3f3f3f3f 
using namespace std;
int n,m,a[maxn],num;
struct node
{
    int l,r,lc,rc;
    int Max,Min,ans;
}t[maxn*4];
int init()
{
    int x=0;char s=getchar();while(s<'0'||s>'9')s=getchar();
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}return x;
}
void Build(int li,int ri)
{
    int k=++num;
    t[k].l=li,t[k].r=ri;
    if(li!=ri-1)
      {
          t[k].lc=num+1;Build(li,(li+ri)/2);
          t[k].rc=num+1;Build((li+ri)/2,ri);
          t[k].Max=max(t[t[k].lc].Max,t[t[k].rc].Max);
          t[k].Min=min(t[t[k].lc].Min,t[t[k].rc].Min);
          t[k].ans=max(t[t[k].rc].Max-t[t[k].lc].Min,max(t[t[k].lc].ans,t[t[k].rc].ans));
      }
    else {t[k].ans=-inf;t[k].Max=a[li];t[k].Min=a[li];}
}
void Change(int k,int li,int ri,int data)
{
    if(li<=t[k].l&&ri>=t[k].r)
      {
          t[k].Max=data;t[k].Min=data;
          t[k].ans=-inf;return;
      }
    int mid=(t[k].l+t[k].r)/2;
    if(li<mid)Change(t[k].lc,li,ri,data);
    if(ri>mid)Change(t[k].rc,li,ri,data);
    t[k].Max=max(t[t[k].lc].Max,t[t[k].rc].Max);
    t[k].Min=min(t[t[k].lc].Min,t[t[k].rc].Min);
    t[k].ans=max(t[t[k].rc].Max-t[t[k].lc].Min,max(t[t[k].lc].ans,t[t[k].rc].ans));
} 
int Query_max(int k,int li,int ri)
{
    if(li<=t[k].l&&ri>=t[k].r)return t[k].Max;
    int ret=-inf,mid=(t[k].l+t[k].r)/2;
    if(li<mid)ret=max(ret,Query_max(t[k].lc,li,ri));
    if(ri>mid)ret=max(ret,Query_max(t[k].rc,li,ri));
    return ret;
}
int Query_min(int k,int li,int ri)
{
    if(li<=t[k].l&&ri>=t[k].r)return t[k].Min;
    int ret=inf,mid=(t[k].l+t[k].r)/2;
    if(li<mid)ret=min(ret,Query_min(t[k].lc,li,ri));
    if(ri>mid)ret=min(ret,Query_min(t[k].rc,li,ri));
    return ret;
}
int Query(int k,int li,int ri)
{
    if(li<=t[k].l&&ri>=t[k].r)return t[k].ans;
    int ret=-inf,mid=(t[k].l+t[k].r)/2;
    if(li<mid)ret=max(ret,Query(t[k].lc,li,ri));
    if(ri>mid)ret=max(ret,Query(t[k].rc,li,ri));
    if(li<mid&&ri>mid)ret=max(ret,Query_max(t[k].rc,mid,ri)-Query_min(t[k].lc,li,mid));
    return ret;
}
int main()
{
    n=init();m=init();
    for(int i=1;i<=n;i++)
      a[i]=init();
    Build(1,n+1);int x,y,z;
    for(int i=1;i<=m;i++)
      {
          x=init();y=init();z=init();
          if(x==1)Change(1,y,y+1,z);
        if(x==2)printf("%d\n",Query(1,y,z+1));
      }
    return 0;
}

 

posted @ 2016-07-18 20:48  一入OI深似海  阅读(176)  评论(0编辑  收藏  举报