Codevs 1080 线段树练习(线段树&&树状数组&&分块&&CDQ分治)
来源:互联网 发布:php.ini session 设置 编辑:程序博客网 时间:2024/05/22 04:31
1080 线段树练习
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
传送门
题目描述 Description
一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1≤N<100000,,提问和修改的总数m<10000条。
输入描述 Input Description
输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和。
输出描述 Output Description
共m行,每个整数
样例输入 Sample Input
6
4
5
6
2
1
3
4
1 3 5
2 1 4
1 1 9
2 2 6
样例输出 Sample Output
22
22
数据范围及提示 Data Size & Hint
1≤N≤100000, m≤10000 。
/*最裸线段树(闭区间版). 支持单点修改+区间求和.*/#include<iostream>#include<cstdio>#define MAXN 100001using namespace std;struct data{ int r,l; int rc,lc; int sum; int bj; int tot;}tree[MAXN*4];int n,m,cut,aa[MAXN+10];void bluid(int l,int r)//建树 { int k=++cut; tree[k].l=l; tree[k].r=r; if(l==r) { tree[k].sum=aa[l]; return ; } int mid=(l+r)>>1; tree[k].lc=cut+1; bluid(l,mid); tree[k].rc=cut+1; bluid(mid+1,r); tree[k].sum=tree[tree[k].lc].sum+tree[tree[k].rc].sum;}void add(int k,int x,int add1)//单点修改 { if(tree[k].l==tree[k].r) tree[k].sum+=add1; else { int mid=(tree[k].l+tree[k].r)>>1; if(x<=mid) add(tree[k].lc,x,add1); if(x>mid) add(tree[k].rc,x,add1); tree[k].sum=tree[tree[k].lc].sum+tree[tree[k].rc].sum; }}int query(int k,int ll,int rr)//区间求和 { if(ll<=tree[k].l&&tree[k].r<=rr) { return tree[k].sum; } int tot=0; int mid=(tree[k].l+tree[k].r)>>1; if(ll<=mid) tot+=query(tree[k].lc,ll,rr); if(rr>mid) tot+=query(tree[k].rc,ll,rr); return tot;}int main(){ int x,a,add1,b; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&aa[i]); } bluid(1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&x); if(x==1) { scanf("%d %d",&a,&add1); add(1,a,add1); } else { scanf("%d %d",&a,&b); printf("%d\n",query(1,a,b)); } } return 0;}
/*最裸线段树(开区间版). 支持单点修改+区间求和.*/#include<iostream>#include<cstdio>#define MAXN 100001using namespace std;struct data{ int r,l; int rc,lc; int sum; int bj; int tot;}tree[MAXN*4];int n,m,cut,aa[MAXN+10];void bluid(int l,int r)//建树 { int k=++cut; tree[k].l=l; tree[k].r=r; if(l==r-1) { tree[k].sum=aa[l]; return ; } int mid=(l+r)>>1; tree[k].lc=cut+1; bluid(l,mid); tree[k].rc=cut+1; bluid(mid,r); tree[k].sum=tree[tree[k].lc].sum+tree[tree[k].rc].sum;}void add(int k,int x,int add1)//单点修改 { if(tree[k].l==tree[k].r-1) tree[k].sum+=add1; else { int mid=(tree[k].l+tree[k].r)>>1; if(x<mid) add(tree[k].lc,x,add1); if(x>=mid) add(tree[k].rc,x,add1); tree[k].sum=tree[tree[k].lc].sum+tree[tree[k].rc].sum; }}int query(int k,int ll,int rr)//区间求和 { if(ll<=tree[k].l&&tree[k].r<=rr) { return tree[k].sum; } int tot=0; int mid=(tree[k].l+tree[k].r)>>1; if(ll<mid) tot+=query(tree[k].lc,ll,rr); if(rr>mid) tot+=query(tree[k].rc,ll,rr); return tot;}int main(){ int x,a,add1,b; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&aa[i]); } bluid(1,n+1); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&x); if(x==1) { scanf("%d %d",&a,&add1); add(1,a,add1); } else { scanf("%d %d",&a,&b); printf("%d\n",query(1,a,b+1)); } } return 0;}
/*树状数组 单点修改 区间求和.比线段树不知道要快到那里去. */#include<cstdio>#include<iostream>#define MAXN 100001int s[MAXN],n,x,y,m,z;int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar(); return x*f;}int lowbit(int t){ return t&-t;}void add(int t,int x){ while(t<=n) { s[t]+=x; t+=lowbit(t); }}int query(int x){ int tot=0; while(x) { tot+=s[x]; x-=lowbit(x); } return tot; }int main(){ n=read(); for(int i=1;i<=n;i++){ x=read(); add(i,x); } m=read(); for(int i=1;i<=m;i++){ z=read();x=read();y=read(); if(z==1) add(x,y); else printf("%d\n",query(y)-query(x-1)); } return 0;}
/*分块.单点修改 区间查询.*/#include<cstdio>#include<cmath>#include<iostream>#define MAXN 100001using namespace std;int n,m,q,ans,s[MAXN],belong[MAXN],sum[MAXN];int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return x*f;}int slovequery(int x,int y){ ans=0; for(int i=x;i<=min(y,belong[x]*m);i++) ans+=s[i]; for(int i=belong[x]+1;i<=belong[y]-1;i++) ans+=sum[i]; if(belong[x]!=belong[y]) for(int i=(belong[y]-1)*m+1;i<=y;i++) ans+=s[i]; return ans;}int main(){ int x,y,z; n=read(); m=sqrt(n); for(int i=1;i<=n;i++) belong[i]=(i-1)/m+1; for(int i=1;i<=n;i++) s[i]=read(),sum[belong[i]]+=s[i]; q=read(); while(q--) { z=read(),x=read(),y=read(); if(z&1) s[x]+=y,sum[belong[x]]+=y; else printf("%d\n",slovequery(x,y)); } return 0;}
/*CDQ分治。对x坐标升序,CDQ分治 维护一个前缀贡献。 */#include<algorithm>#include<cstdio>#define MAXN 100001using namespace std;int s[MAXN],n,m,tot,t,sum,ans[MAXN];struct data{int x,k,t,o,z,belong;}q[MAXN*2],tmp[MAXN*2];int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return x*f;}bool cmp(const data &x,const data &y){ if(x.x!=y.x) return x.x<y.x; else return x.k<y.k;}void slove(int l,int r){ if(l==r) return ; int mid=(l+r)>>1,ll=l,rr=mid+1; for(int i=l;i<=r;i++) { if(q[i].k==1&&q[i].t<=mid) sum+=q[i].z; else if(q[i].k==2&&q[i].t>mid) ans[q[i].belong]+=sum*q[i].z; } for(int i=l;i<=r;i++) { if(q[i].t<=mid) tmp[ll++]=q[i]; else tmp[rr++]=q[i]; } sum=0; for(int i=l;i<=r;i++) q[i]=tmp[i]; slove(l,mid),slove(mid+1,r); return ;}int main(){ int x,y,z; n=read(); for(int i=1;i<=n;i++) x=read(),q[++tot].x=i,q[tot].k=1,q[tot].z=x,q[tot].t=tot; m=read(); for(int i=1;i<=m;i++) { z=read(),x=read(),y=read(); if(z&1) q[++tot].x=x,q[tot].k=1,q[tot].z=y,q[tot].t=tot; else { q[++tot].x=x-1,q[tot].k=2,q[tot].z=-1,q[tot].t=tot,q[tot].belong=++t; q[++tot].x=y,q[tot].k=2,q[tot].z=1,q[tot].t=tot,q[tot].belong=t; } } sort(q+1,q+tot+1,cmp); slove(1,tot); for(int i=1;i<=t;i++) printf("%d\n",ans[i]); return 0;}
“`
0 0
- Codevs 1080 线段树练习(线段树&&树状数组&&分块&&CDQ分治)
- 【CodeVS】1080 线段树练习 分块 线段树 树状数组 开放性
- Codevs 1081 线段树练习 2(线段树&&树状数组&&分块)
- 形形色色的线段树练习——codevs线段树练习1-5:线段树,树状数组及分块模板
- CodeVS 1080 线段树练习 分块 块状数组
- codevs 1080_线段树练习_树状数组
- Codevs 4927 线段树练习5(分块)
- Codevs 1082 线段树练习 3(线段树&&分块)
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- bzoj 1901: Zju2112 Dynamic Rankings 树状数组套线段树 cdq分治
- HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
- HDU6183 cdq分治+线段树
- 【CodeVS】1191 数轴染色 分块 线段树 树状数组 平衡树 开放性
- CODEVS 1080线段树练习
- 1080 线段树练习 codevs
- CODEVS 1080 线段树练习
- [Codevs] 1080 线段树练习
- 【codevs 1080】线段树练习
- Android Studio图文安装教程
- 浅谈设计模式之简单工厂模式、工厂模式、抽象工厂模式
- yum源的更新
- iOS - 通过runtime获取某个类中所有的变量和方法
- 你需要知道的 Android6.0 权限相关
- Codevs 1080 线段树练习(线段树&&树状数组&&分块&&CDQ分治)
- DT大数据梦工厂Spark 定制班笔记(002)
- 关于jspsmartupload 中文各种乱码的解决方法
- 重装系统后,硬盘分区丢失的解决办法
- 存储过程管理过程
- base64编码
- 一些技术大牛的博客集锦(转)
- 你应该知道的浮点数基础知识
- C#—实验8.4、8.5和8.6