• [codevs]: 线段树练习1-4 标签: 线段树 2017-05-29 17:29 40人阅读 评论(0)


    题目较多就不贴了^_^
    都是线段树入门模板题
    1080 线段树练习1
    单点更新+区间查询

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    int w[100010];
    struct node{
        int left;
        int right;
        int sum;
        int addv;
    }a[400040];
    void build(int l,int r,int p){
        a[p].left=l;a[p].right=r;
        if(l==r) {  a[p].sum=w[l];return ;}
        if(l<r){
            build(l,(l+r)/2,2*p);
            build((l+r)/2+1,r,2*p+1);
            a[p].sum=a[2*p].sum+a[2*p+1].sum;
        }
    }
    void pushdown(int p){
        if(a[p].addv!=0){
            a[2*p].addv+=a[p].addv;
            a[2*p].sum+=a[p].addv*(a[2*p].right-a[2*p].left+1);
            a[2*p+1].addv=a[p].addv;
            a[2*p+1].sum+=a[p].addv*(a[2*p+1].right-a[2*p+1].left+1);
            a[p].addv=0;
        }
    }
    void update(int x,int p,int d){
        if(a[p].left==x&&a[p].right==x){
            a[p].sum+=d;a[p].addv+=d;return ;
        }
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(x<=mid) update(x,2*p,d);
        else if(x>mid) update(x,2*p+1,d);
        a[p].sum=a[2*p].sum+a[2*p+1].sum;
    }
    int query(int l,int r,int p){
        if(a[p].left==l&&a[p].right==r)
            return a[p].sum;
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(r<=mid) return query(l,r,2*p);
        else if(l>mid) return query(l,r,2*p+1);
        else return query(l,mid,2*p)+query(mid+1,r,2*p+1);
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        build(1,n,1);
        int m;
        scanf("%d",&m);
        while(m--){
            int k,x,y;
            scanf("%d%d%d",&k,&x,&y);
            if(k==1)
            update(x,1,y);
            else
            printf("%d
    ",query(x,y,1));
        }
        return 0;
    }
    

    线段树练习2
    区间更新+单点查询

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    int w[100010];
    struct node{
        int left;
        int right;
        int sum;
        int addv;
    }a[400040];
    void build(int l,int r,int p){
        a[p].left=l;a[p].right=r;
        if(l==r) {  a[p].sum=w[l];return ;}
        if(l<r){
            build(l,(l+r)/2,2*p);
            build((l+r)/2+1,r,2*p+1);
            a[p].sum=a[2*p].sum+a[2*p+1].sum;
        }
    }
    void pushdown(int p){
        if(a[p].addv!=0){
            a[2*p].addv+=a[p].addv;
            a[2*p].sum+=a[p].addv*(a[2*p].right-a[2*p].left+1);
            a[2*p+1].addv+=a[p].addv;
            a[2*p+1].sum+=a[p].addv*(a[2*p+1].right-a[2*p+1].left+1);
            a[p].addv=0;
        }
    }
    void update(int l,int r,int p,int d){
        if(a[p].left==l&&a[p].right==r){
            a[p].sum+=d;a[p].addv+=d;return ;
        }
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(r<=mid) update(l,r,2*p,d);
        else if(l>mid) update(l,r,2*p+1,d);
        else{
            update(l,mid,2*p,d);update(mid+1,r,2*p+1,d);
        }
        a[p].sum=a[2*p].sum+a[2*p+1].sum;
    }
    int query(int x,int p){
        if(a[p].left==x&&a[p].right==x)
            return a[p].sum;
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(x<=mid) return query(x,2*p);
        else if(x>mid) return query(x,2*p+1);
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        build(1,n,1);
        int m;
        scanf("%d",&m);
        while(m--){
            int k,x,y,d;
            scanf("%d",&k);
            if(k==1){
                scanf("%d%d%d",&x,&y,&d);
                update(x,y,1,d);
            }
            else {
                scanf("%d",&x);
                printf("%d
    ",query(x,1));
            }
        }
        return 0;
    }
    

    线段树练习3
    区间更新+区间查询

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    int w[200010];
    struct node{
        int left;
        int right;
        ll sum;
        ll addv;
    }a[800080];
    void build(int l,int r,int p){
        a[p].left=l;a[p].right=r;
        if(l==r) {  a[p].sum=w[l];return ;}
        if(l<r){
            build(l,(l+r)/2,2*p);
            build((l+r)/2+1,r,2*p+1);
            a[p].sum=a[2*p].sum+a[2*p+1].sum;
        }
    }
    void pushdown(int p){
        if(a[p].addv!=0){
            a[2*p].addv+=a[p].addv;
            a[2*p].sum+=a[p].addv*(a[2*p].right-a[2*p].left+1);
            a[2*p+1].addv+=a[p].addv;
            a[2*p+1].sum+=a[p].addv*(a[2*p+1].right-a[2*p+1].left+1);
            a[p].addv=0;
        }
    }
    void update(int l,int r,int p,int d){
        if(a[p].left==l&&a[p].right==r){
            a[p].sum+=(r-l+1)*d;a[p].addv+=d;return ;
        }
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(r<=mid) update(l,r,2*p,d);
        else if(l>mid) update(l,r,2*p+1,d);
        else{
            update(l,mid,2*p,d);update(mid+1,r,2*p+1,d);
        }
        a[p].sum=a[2*p].sum+a[2*p+1].sum;
    }
    ll query(int l,int r,int p){
        if(a[p].left==l&&a[p].right==r)
            return a[p].sum;
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(r<=mid) return query(l,r,2*p);
        else if(l>mid) return query(l,r,2*p+1);
        else return query(l,mid,2*p)+query(mid+1,r,2*p+1);
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        build(1,n,1);
        int m;
        scanf("%d",&m);
        while(m--){
            int k,x,y;
            ll d;
            scanf("%d",&k);
            if(k==1){
                scanf("%d%d%lld",&x,&y,&d);
                update(x,y,1,d);
            }
            else {
                scanf("%d%d",&x,&y);
                printf("%lld
    ",query(x,y,1));
            }
        }
        return 0;
    }

    线段树练习4
    嗯 此题有点变化  难度高于上面三题   区间更新+求%7==0的
    方法就是记录下mod7的余数 然后每次做加法相当于向右平移数组元素
    addv这个加值记录平移量 然后就没了。。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define N 100010
    using namespace std;
    int w[N];int temp[N];
    struct node{
        int left;
        int right;
        int sum[7];
        int addv;
    }a[4*N];
    void build(int l,int r,int p){
        a[p].left=l;a[p].right=r;
        if(l==r){ a[p].sum[w[l]%7]++; return;}
        if(l<r) {
            build(l,(l+r)/2,2*p);
            build((l+r)/2+1,r,2*p+1);
            for(int i=0;i<=6;i++)
                a[p].sum[i]=a[2*p].sum[i]+a[2*p+1].sum[i];
        }
    }
    void deal(int p,int k){
    //平移函数
        if(k!=0){
            for(int i=0;i<=6;i++)
                temp[(i+k)%7]=a[p].sum[i];
            for(int i=0;i<=6;i++)
                a[p].sum[i]=temp[i];
        }
    }
    void pushdown(int p){
    //往下传值函数
        if(a[p].addv!=0){
            a[2*p].addv+=a[p].addv;
            deal(2*p,a[p].addv);
            a[2*p+1].addv+=a[p].addv;
            deal(2*p+1,a[p].addv);
            a[p].addv=0;
        }
    }
    void update(int l,int r,int p,int x){
        if(a[p].left==l&&a[p].right==r)
        {deal(p,x); a[p].addv+=x; return;}
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(r<=mid)  update(l,r,2*p,x);
        else if(l>mid) update(l,r,2*p+1,x);
        else {
            update(l,mid,2*p,x);
            update(mid+1,r,2*p+1,x);
        }
        for(int i=0;i<=6;i++)
            a[p].sum[i]=a[2*p].sum[i]+a[2*p+1].sum[i];
    }
    int query(int l,int r,int p){
        if(a[p].left==l&&a[p].right==r)
            return a[p].sum[0];
        pushdown(p);
        int mid=(a[p].left+a[p].right)/2;
        if(r<=mid) return query(l,r,2*p);
        else if(l>mid) return query(l,r,2*p+1);
        else return query(l,mid,2*p)+query(mid+1,r,2*p+1);
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            w[i]=x%7;
        }
        build(1,n,1);
        int m;
        scanf("%d",&m);
        char ss[10];
        while(m--){
            getchar();
            scanf("%s",&ss);
            int x,y,k;
            if(ss[0]=='c') {
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(x,y,1));
            }
            else {
                scanf("%d%d%d",&x,&y,&k);
                k%=7;
    //时刻记得mod7
                update(x,y,1,k);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    UDP协议发送/接收数据实现[TCP/IP协议入门]
    TCP协议发送/接收数据实现[TCP/IP协议入门]
    vue 打包后的build文件过大解决方案
    vuecli 性能优化
    局域网内开启ps登录windows功能
    判断是否是手机浏览器
    java通过模拟post方式提交表单实现图片上传功能实例
    C#中遍历Hashtable的4种方法
    Springboot使用RestTemplate发送Post请求postForEntity (application/json)的坑
    lerna存在的必要性
  • 原文地址:https://www.cnblogs.com/xljxlj/p/7183639.html
Copyright © 2020-2023  润新知