[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;}
阅读全文
0 0
- [codevs]: 线段树练习1-4
- [codevs] 线段树练习4
- Codevs 4919 线段树练习4
- <线段树系列4> codevs 4927 线段树练习5
- codevs线段树练习3
- CODEVS 1080线段树练习
- 1080 线段树练习 codevs
- CODEVS 1080 线段树练习
- [Codevs] 1080 线段树练习
- 【codevs 1080】线段树练习
- <线段树系列1> codevs 1080 线段树练习
- CODEVS-1082-线段树练习3-splay
- 【codevs 1080~1082】线段树练习重做
- 【codevs 1082】线段树练习3
- CODEVS 1081线段树练习2
- [题解] codevs 1080 线段树练习
- Codevs 4927 线段树练习5(分块)
- CODEVS 1081 线段树练习 2
- Rxjava
- Unity顶点着色器和片段着色器
- 二叉树深度优先和广度优先遍历
- java类的引用使用即String类的toUpperCase的使用
- U-Boot源代码阅读笔记(二) —— 对lowlevel_init.S的分析
- [codevs]: 线段树练习1-4
- Mybatis5.0.2分页插件
- bmob和okgo的冲突
- javaoop总结
- python3_字典
- hibernate-关系映射(一对一(单向、双向))-8
- EasyDarwin开源流媒体服务器中一种实现对作用域内new对象自动释放的方法(值得借鉴)
- lowlevel_init.S 分析
- IMWeb提升营Day5 | 训练题27:字符串的排列