暑假集训每日一题0711 (线段树)

维护一个整数序列,支持以下操作:
1 x v : 将第x个整数的值修改为v;
2 x y : 查询区间[x,y]之间的最小值;
3 x y : 查询区间[x,y]之间的最大值;
4 x y : 查询区间[x,y]内的整数和。

数据保证查询结果均在int范围之内,但中间结果是否可能溢出呢?我交的程序没考虑这个也AC了。

通过这题还发现一个奇怪的现象,用memset初始化的程序跑了2s多,而用for循环初始化的程序才跑468ms……

for循环初始化(468ms)
#include <stdio.h>
#include <string.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define INF 0x7fffffff
#define N 100010
int D,n;
int v[N],min[4*N],max[4*N],sum[4*N];
void init()
{
    int i;
    for(i=1;i<2*D;i++)
    {
        min[i]=INF;
        max[i]=-INF;
        sum[i]=0;
    }
    for(D=1;D<n+2;D<<=1);
    for(i=1;i<=n;i++)
    {
        min[D+i]=max[D+i]=sum[D+i]=v[i];
    }
    for(i=D-1;i^1;i--)
    {
        min[i]=MIN(min[i<<1],min[i<<1|1]);
        max[i]=MAX(max[i<<1],max[i<<1|1]);
        sum[i]=sum[i<<1]+sum[i<<1|1];
    }
}
void update(int k,int v)
{
    int i;
    min[D+k]=max[D+k]=sum[D+k]=v;
    for(i=D+k;i^1;i>>=1)
    {
        min[i>>1]=MIN(min[i],min[i^1]);
        max[i>>1]=MAX(max[i],max[i^1]);
        sum[i>>1]=sum[i]+sum[i^1];
    }
}
void getmin(int x,int y)
{
    int i=D+x-1,j=D+y+1,ret=INF;
    for(;i^j^1;i>>=1,j>>=1)
    {
        if(~i&1)    ret=MIN(ret,min[i^1]);
        if(j&1) ret=MIN(ret,min[j^1]);
    }
    printf("%d\n",ret);
}
void getmax(int x,int y)
{
    int i=D+x-1,j=D+y+1,ret=-INF;
    for(;i^j^1;i>>=1,j>>=1)
    {
        if(~i&1)    ret=MAX(ret,max[i^1]);
        if(j&1) ret=MAX(ret,max[j^1]);
    }
    printf("%d\n",ret);
}
void getsum(int x,int y)
{
    int i=D+x-1,j=D+y+1,ret=0;
    for(;i^j^1;i>>=1,j>>=1)
    {
        if(~i&1)    ret+=sum[i^1];
        if(j&1) ret+=sum[j^1];
    }
    printf("%d\n",ret);
}
int main()
{
    int i,m,opt,x,y;
    while(~scanf("%d",&n))
    {
        for(i=1;i<=n;i++)   scanf("%d",&v[i]);
        scanf("%d",&m);
        init();
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&opt,&x,&y);
            switch(opt)
            {
                case 1: update(x,y);    break;
                case 2: getmin(x,y);    break;
                case 3: getmax(x,y);    break;
                case 4: getsum(x,y);    break;
            }
        }
    }
    return 0;
}
memset初始化(2s多)
#include <stdio.h>
#include <string.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define INF 0x7fffffff
#define N 100010
int D,n;
int v[N],min[4*N],max[4*N],sum[4*N];
void init()
{
    int i;
    memset(min,0x3f,sizeof(min));
    memset(max,0xc3,sizeof(max));
    memset(sum,0,sizeof(sum));
    for(D=1;D<n+2;D<<=1);
    for(i=1;i<=n;i++)
    {
        min[D+i]=max[D+i]=sum[D+i]=v[i];
    }
    for(i=D-1;i^1;i--)
    {
        min[i]=MIN(min[i<<1],min[i<<1|1]);
        max[i]=MAX(max[i<<1],max[i<<1|1]);
        sum[i]=sum[i<<1]+sum[i<<1|1];
    }
}
void update(int k,int v)
{
    int i;
    min[D+k]=max[D+k]=sum[D+k]=v;
    for(i=D+k;i^1;i>>=1)
    {
        min[i>>1]=MIN(min[i],min[i^1]);
        max[i>>1]=MAX(max[i],max[i^1]);
        sum[i>>1]=sum[i]+sum[i^1];
    }
}
void getmin(int x,int y)
{
    int i=D+x-1,j=D+y+1,ret=INF;
    for(;i^j^1;i>>=1,j>>=1)
    {
        if(~i&1)    ret=MIN(ret,min[i^1]);
        if(j&1) ret=MIN(ret,min[j^1]);
    }
    printf("%d\n",ret);
}
void getmax(int x,int y)
{
    int i=D+x-1,j=D+y+1,ret=-INF;
    for(;i^j^1;i>>=1,j>>=1)
    {
        if(~i&1)    ret=MAX(ret,max[i^1]);
        if(j&1) ret=MAX(ret,max[j^1]);
    }
    printf("%d\n",ret);
}
void getsum(int x,int y)
{
    int i=D+x-1,j=D+y+1,ret=0;
    for(;i^j^1;i>>=1,j>>=1)
    {
        if(~i&1)    ret+=sum[i^1];
        if(j&1) ret+=sum[j^1];
    }
    printf("%d\n",ret);
}
int main()
{
    int i,m,opt,x,y;
    while(~scanf("%d",&n))
    {
        for(i=1;i<=n;i++)   scanf("%d",&v[i]);
        scanf("%d",&m);
        init();
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&opt,&x,&y);
            switch(opt)
            {
                case 1: update(x,y);    break;
                case 2: getmin(x,y);    break;
                case 3: getmax(x,y);    break;
                case 4: getsum(x,y);    break;
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/algorithms/p/2586138.html