• 暑假集训每日一题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;
    }
  • 相关阅读:
    Android 锁屏 临时屏蔽
    单编译framework相关模块
    02
    pad 强制加载 Hdpi资源 (2.3 dpi < 240)
    设置form的默认按钮
    How to Be a Good Graduate Student
    我怕你们急于求成
    希腊字母读音表
    数据库札记(二)
    Ubuntu 9.04下jdk的安装与配置
  • 原文地址:https://www.cnblogs.com/algorithms/p/2586138.html
Copyright © 2020-2023  润新知