[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;
}
原文地址:https://www.cnblogs.com/xljxlj/p/7183639.html