[codevs]: 线段树练习1-4
2017-05-29 17:29
375 查看
题目较多就不贴了^_^
都是线段树入门模板题
1080 线段树练习1
单点更新+区间查询
线段树练习2
区间更新+单点查询
线段树练习3
区间更新+区间查询
线段树练习4
嗯 此题有点变化 难度高于上面三题 区间更新+求%7==0的
方法就是记录下mod7的余数 然后每次做加法相当于向右平移数组元素
addv这个加值记录平移量 然后就没了。。
都是线段树入门模板题
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 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< 10491 /span>*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 100010 using namespace std; int w ;int temp ; 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; }
相关文章推荐
- 【codevs 1080】线段树练习(单点修改+区间和)
- CodeVS4919 线段树练习4
- 【codevs3304】水果姐逛水果街Ⅰ 线段树练习
- [Codevs] 1080 线段树练习
- codevs1081 线段树练习 2<区间修改>
- codevs1080线段树练习(zkw线段树)
- codevs 1081 线段树练习 2 线段树
- 线段树模版(codevs1081线段树练习2)
- 【CODE[VS]】1082 线段树练习 3 树状数组
- [Codevs] 1080 线段树练习
- 【codevs 1080~1082】线段树练习重做
- Codevs 1080 线段树练习(CDQ分治)
- [CodeVS1081]线段树练习2(区间修改+单点询问)
- [CodeVS4919]线段树练习4
- 【codevs1082】线段树练习3——树状数组(改段求段)
- Codevs1082 线段树练习三(树状数组)
- [Codevs] 1082 线段树练习3
- codevs 4919 线段树练习4
- [题解] codevs 1080 线段树练习
- [codevs] 线段树练习4