1. 程式人生 > >NOIP 資訊學 奧賽 考綱 考點 模板 裸題 水題

NOIP 資訊學 奧賽 考綱 考點 模板 裸題 水題

  • //洛谷 P3372 【模板】線段樹 1
    //調了會,樣例通過,提交AC 2018-5-8 收穫是 對 線段樹 理解更深刻了
    #include <stdio.h>
    #include <string.h>
    #define maxn 100100
    #define LL long long
    LL n,m,lazy[4*maxn],ans,max_k=-999999999;
    struct node{
        LL left,right,v;
    }q[4*maxn];
    void build(LL k,LL left,LL right){
        LL mid=(left+right)/2;
        q[k].left=left,q[k].right=right;
        if(q[k].left==q[k].right){
            scanf("%lld",&q[k].v);
            if(max_k<k)max_k=k;//判斷最大節點位置
            return ;
        }
        build(2*k,left,mid);
        build(2*k+1,mid+1,right);
        q[k].v=q[2*k].v+q[2*k+1].v;
    }
    void down(LL k){
        LL v=lazy[k];
        //此處多寫了此句q[k].v+=(q[k].right-q[k].left+1)*v;
        if(2*k<=max_k){//判斷有無越界
            lazy[2*k]+=v;
            q[2*k].v+=(q[2*k].right-q[2*k].left+1)*v;//漏了此句
        }
        if(2*k+1<=max_k){//判斷有無越界
            lazy[2*k+1]+=v;
            q[2*k+1].v+=(q[2*k+1].right-q[2*k+1].left+1)*v;//漏了此句
        }
        lazy[k]=0;
    }
    void query(LL k,LL left,LL right){
        LL mid=(q[k].left+q[k].right)/2;//此處寫成 LL mid=(left+right)/2;
        if(left<=q[k].left&&q[k].right<=right){
            ans+=q[k].v;
            return ;
        }
        if(lazy[k])down(k);
        if(left<=mid)query(2*k,left,right);
        if(right>=mid+1)query(2*k+1,left,right);
    }
    void add(LL k,LL left,LL right,LL v){
        LL mid=(q[k].left+q[k].right)/2;//此處寫成 LL mid=(left+right)/2;
        if(left<=q[k].left&&q[k].right<=right){
            q[k].v+=(q[k].right-q[k].left+1)*v;
            lazy[k]+=v;//漏了此句
            return ;
        }
        if(lazy[k])down(k);
        if(left<=mid)add(2*k,left,right,v);//此處寫成 query(2*k,left,right)昏招
        if(right>=mid+1)add(2*k+1,left,right,v);//此處寫成 query(2*k+1,left,right)昏招
        q[k].v=q[2*k].v+q[2*k+1].v;
    }
    int main(){
        LL i,cmd,x,y,v;
        scanf("%lld%lld",&n,&m);
        build(1,1,n);
        memset(lazy,0,sizeof(lazy));
        while(m--){
            scanf("%lld",&cmd);
            if(cmd==2){
                ans=0;
                scanf("%lld%lld",&x,&y);
                query(1,x,y);
                printf("%lld\n",ans);
            }else{//cmd==1
                scanf("%lld%lld%lld",&x,&y,&v);
                add(1,x,y,v);
            }
        }
        return 0;
    }

    //P3372 【模板】線段樹 1
    //列舉的方式,猜測70分。
    //果然,提交70分,測試點8,9,10 TLE 2018-5-7 18:01
    #include <stdio.h>
    #define maxn 100100
    #define LL long long
    LL a[maxn];
    int main(){
        LL n,m,i,j,cmd,x,y,k,sum;
        scanf("%lld%lld",&n,&m);
        for(i=1;i<=n;i++)scanf("%lld",&a[i]);
        while(m--){
            scanf("%lld",&cmd);
            if(cmd==1){
                scanf("%lld%lld%lld",&x,&y,&k);
                for(i=x;i<=y;i++)a[i]+=k;
            }else{
                sum=0;
                scanf("%lld%lld",&x,&y);
                for(i=x;i<=y;i++)sum+=a[i];
                printf("%lld\n",sum);
            }
        }
        return 0;
    }