[codevs]: 线段树练习1-4

来源:互联网 发布:赵丽颖电影知乎 编辑:程序博客网 时间:2024/04/30 04:20

题目较多就不贴了^_^
都是线段树入门模板题
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\n",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\n",query(x,1));        }    }    return 0;}

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

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#define ll long longint 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\n",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 100010using 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\n",query(x,y,1));        }        else {            scanf("%d%d%d",&x,&y,&k);            k%=7;//时刻记得mod7            update(x,y,1,k);        }    }    return 0;}
原创粉丝点击