【POJ3468】A Simple Problem with Integers-线段树和伸展树入门题
来源:互联网 发布:软件著作权个人申请 编辑:程序博客网 时间:2024/06/06 12:58
(本人本题完成于2016-7-23)
(已于2016-8-29更新伸展树做法)
题目大意:有一个数列A有N个数,对这个数列有两种操作:1.C a b c:将Aa,Aa+1,...,Ab都加上c。2.Q a b:询问Aa,Aa+1,...,Ab的和。根据询问给出答案。
做法:一道非常裸的线段树题,没什么可说的,由于数字较大需用long long。
(2016.8.29更新:此题也为伸展树区间处理的入门题,但感觉似乎有些小题大做...不过当做模板参照一下也是好的,所以也将代码陈列在这里。)
以下是本人代码:
线段树:
#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;int n,q,a,b;long long A[100010]={0},c;char o;struct node{ int l,r; long long sum,p;}seg[300010];void buildtree(int no,int l,int r){ int mid=(l+r)/2; seg[no].l=l;seg[no].r=r;seg[no].p=0; if (l==r) seg[no].sum=A[l]; else { buildtree(2*no,l,mid);buildtree(2*no+1,mid+1,r);seg[no].sum=seg[2*no].sum+seg[2*no+1].sum; }}void add(int no,int s,int t,long long c){ int mid=(seg[no].l+seg[no].r)/2; if (seg[no].l>=s&&seg[no].r<=t) { seg[no].p+=c;seg[no].sum+=(long long)(seg[no].r-seg[no].l+1)*c; return; } seg[2*no].p+=seg[no].p;seg[2*no+1].p+=seg[no].p; seg[2*no].sum+=(long long)(seg[2*no].r-seg[2*no].l+1)*seg[no].p; seg[2*no+1].sum+=(long long)(seg[2*no+1].r-seg[2*no+1].l+1)*seg[no].p; seg[no].p=0; if (s<=mid) add(2*no,s,t,c); if (t>mid) add(2*no+1,s,t,c); seg[no].sum=seg[2*no].sum+seg[2*no+1].sum;}long long query(int no,int s,int t){ int mid=(seg[no].l+seg[no].r)/2; if (seg[no].l>=s&&seg[no].r<=t) return seg[no].sum; seg[2*no].p+=seg[no].p;seg[2*no+1].p+=seg[no].p; seg[2*no].sum+=(long long)(seg[2*no].r-seg[2*no].l+1)*seg[no].p; seg[2*no+1].sum+=(long long)(seg[2*no+1].r-seg[2*no+1].l+1)*seg[no].p; seg[no].p=0; long long tot=0; if (s<=mid) tot+=query(2*no,s,t); if (t>mid) tot+=query(2*no+1,s,t); return tot;}int main(){ scanf("%d %d",&n,&q); for(int i=1;i<=n;i++) scanf("%lld",&A[i]); scanf("\n"); buildtree(1,1,n); for(int i=1;i<=q;i++) { scanf("%c",&o);if (o=='C'){ scanf("%d %d %lld\n",&a,&b,&c); add(1,a,b,c);}if (o=='Q'){ scanf("%d %d\n",&a,&b); printf("%lld\n",query(1,a,b));} } return 0;}
伸展树(2016.8.29更新):
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;long long n,q,num[100010],root=0,top=0;long long val[100010],sum[100010],p[100010],siz[100010],ch[100010][2],pre[100010];char op[20];void newnode(long long &x,long long c,long long f){ x=++top; ch[x][0]=ch[x][1]=0;siz[x]=1; val[x]=sum[x]=c;p[x]=0; pre[x]=f;}void pushdown(long long x){ if (!p[x]) return; int l=ch[x][0],r=ch[x][1]; p[l]+=p[x];p[r]+=p[x]; val[l]+=p[x];val[r]+=p[x]; sum[l]+=siz[l]*p[x]; sum[r]+=siz[r]*p[x]; p[x]=0;}void pushup(long long x){ siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];}void rotate(long long x,bool f){ long long y=pre[x]; pushdown(y);pushdown(x); ch[y][!f]=ch[x][f]; pre[ch[x][f]]=y; ch[x][f]=y; if (pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];pre[y]=x; pushup(y);}void Splay(long long x,int goal){ pushdown(x); while (pre[x]!=goal) { pushdown(pre[pre[x]]);pushdown(pre[x]);pushdown(x);if (pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);else{ bool f=(ch[pre[pre[x]]][0]==pre[x]); if (ch[pre[x]][f]==x) rotate(x,!f),rotate(x,f); else rotate(pre[x],f),rotate(x,f); } } pushup(x); if (goal==0) root=x;}void rotateto(long long k,long long goal){ long long i=root; pushdown(i); while(siz[ch[i][0]]+1!=k) { if (siz[ch[i][0]]+1<k) k-=siz[ch[i][0]]+1,i=ch[i][1];else i=ch[i][0];pushdown(i); } Splay(i,goal);}void buildtree(long long &x,long long l,long long r,long long f){ if (l>r) return; long long mid=(l+r)>>1; newnode(x,num[mid],f); buildtree(ch[x][0],l,mid-1,x); buildtree(ch[x][1],mid+1,r,x); pushup(x);}void input(){ ch[0][0]=ch[0][1]=siz[0]=sum[0]=p[0]=pre[0]=val[0]=0; newnode(root,-1,0); newnode(ch[root][1],-1,root); siz[root]=2; for(int i=1;i<=n;i++) scanf("%lld",&num[i]); buildtree(ch[ch[root][1]][0],1,n,ch[root][1]); pushup(ch[root][1]);pushup(root);}void change(long long s,long long t,long long v){ rotateto(s,0); rotateto(t+2,root); long long g=ch[ch[root][1]][0]; val[g]+=v; p[g]+=v; sum[g]+=siz[g]*v;}long long query(long long s,long long t){ rotateto(s,0); rotateto(t+2,root); long long g=ch[ch[root][1]][0]; return sum[g];}int main(){ scanf("%lld%lld",&n,&q); input(); for(int i=1;i<=q;i++) { long long s,t,v; scanf("%s",op);if (op[0]=='C'){ scanf("%lld%lld%lld",&s,&t,&v); change(s,t,v); }if (op[0]=='Q'){ scanf("%lld%lld",&s,&t); printf("%lld\n",query(s,t));} } return 0;}
0 0
- 【POJ3468】A Simple Problem with Integers-线段树和伸展树入门题
- kyeremal-poj3468-A simple Problem with Integers-伸展树
- poj3468 A Simple Problem with Integers 线段树入门题复习
- poj3468 A Simple Problem with Integers 线段树的扩展
- poj3468- A Simple Problem with Integers-解题报告-线段树
- poj3468 A Simple Problem with Integers(spaly&&线段树)
- poj3468 A Simple Problem with Integers(线段树)
- poj3468 A Simple Problem with Integers 线段树区间更新
- poj3468(A Simple Problem with Integers)线段树实现
- POJ3468---线段树模版--A Simple Problem with Integers
- POJ3468 A Simple Problem with Integers 【线段树+lazy】
- [线段树] poj3468 A Simple Problem with Integers
- POJ3468 A Simple Problem with Integers(线段树)
- 线段树专题 POJ3468 A Simple Problem with Integers
- POJ3468,A Simple Problem with Integers,线段树
- poj3468 A Simple Problem with Integers 线段树 延时更新
- poj3468 A Simple Problem with Integers(线段树)
- poj3468 A Simple Problem with Integers 线段树lazy标签
- geekband_c++学习笔记1
- key set
- windows下Qt5.1 for android开发环境配置
- android:shape属性详解
- 贪心算法
- 【POJ3468】A Simple Problem with Integers-线段树和伸展树入门题
- MVVM介绍
- 内存管理:栈区,堆区,全局区,文字常量区,程序代码区
- Hust oj 1033 487-3279(map)
- 求最大公约数和最小公倍数
- throw与throws的区别
- 模仿支付宝咻一咻
- 离开易拓网络的第二天,待在图书馆
- POJ 3450--->Corporate Identity(后缀数组求多个字符串的公共子串)