正题

题目链接:我是链接
其实洛谷线段树模板也是一样的:三种方法AC评测链接


题目大意

要求支持区间修改,区间求和。


线段树

直接用一个lazy标记,在之前的博客里有说


code1

#include<cstdio>
#include<algorithm>
#define N 100010
#define ll long long
using namespace std;
struct treenode{int l,r;ll val,lazy;
}t[N*4];
int n,m,l,r;
ll x;
char c[2];
void build(int x,int l,int r)//建树
{t[x].l=l;t[x].r=r;if(l==r){scanf("%lld",&t[x].val);return;}int mid=(l+r)>>1;build(x*2,l,mid);build(x*2+1,mid+1,r);t[x].val=t[x*2].val+t[x*2+1].val;
}
void downdata(int x)//下传标记
{if(t[x].lazy){t[x*2].lazy+=t[x].lazy;t[x*2].val+=t[x].lazy*(t[x*2].r-t[x*2].l+1);t[x*2+1].lazy+=t[x].lazy;t[x*2+1].val+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1);t[x].lazy=0;}
}
void change(int x,int l,int r,ll num)//区间修改
{if(t[x].l==l&&t[x].r==r){t[x].val+=num*(t[x].r-t[x].l+1);t[x].lazy+=num;return;}downdata(x);int mid=(t[x].l+t[x].r)>>1;if(r<=mid) change(x*2,l,r,num);else if(l>mid) change(x*2+1,l,r,num);else change(x*2,l,mid,num),change(x*2+1,mid+1,r,num);t[x].val=t[x*2].val+t[x*2+1].val;
}
ll find(int x,int l,int r)//区间查询
{if(t[x].l==l&&t[x].r==r)return t[x].val;downdata(x);int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return find(x*2,l,r);else if(l>mid) return find(x*2+1,l,r);else return find(x*2,l,mid)+find(x*2+1,mid+1,r);
}
int main()
{scanf("%d%d",&n,&m);build(1,1,n);for(int i=1;i<=m;i++){scanf("%s %d %d",c,&l,&r);if(c[0]=='Q') printf("%lld\n",find(1,l,r));else{scanf("%lld",&x);change(1,l,r,x);}}
}

树状数组

我们可以用树状数组维护一个查分数组bbb和一个bi×i" role="presentation" style="position: relative;">bi×ibi×ib_i\times i的前缀和,然后再记录原来的a数组的前缀和sumsumsum,对于改写我们就将两个数组改变,然后查询就

(sumr+(r+1)∗ask(c0,r)−ask(c1,r))−(suml−1+l∗ask(c1,l−1)−ask(c1,l−1)(sumr+(r+1)∗ask(c0,r)−ask(c1,r))−(suml−1+l∗ask(c1,l−1)−ask(c1,l−1)

(sum_r+(r+1)*ask(c_0,r)-ask(c_1,r))-(sum_{l-1}+l*ask(c_1,l-1)-ask(c_1,l-1)


code2

#include<cstdio>
#include<algorithm>
#include<iostream>
#define lobit(x) x&-x
using namespace std;
long long t[2][100010],x,a[100010],sum[100010];
int n,m,l,r;
void add(int k,int x,int num)//修改
{while(x<=n){t[k][x]+=num;x+=lobit(x);}
}
long long ask(int k,int x)//查询
{long long sum=0;while(x>0){sum+=t[k][x];x-=lobit(x);}return sum;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];}for(int i=1;i<=m;i++){char c[2];scanf("%s %d %d",c,&l,&r);if(c[0]=='Q'){long long ans=sum[r]+(r+1)*ask(0,r)-ask(1,r);ans-=sum[l-1]+l*ask(0,l-1)-ask(1,l-1);//查询printf("%lld\n",ans);}else{scanf("%d",&x);add(0,l,x);add(0,r+1,-x);add(1,l,l*x);add(1,r+1,-(r+1)*x);//修改}}
}

分块

将整段分成多块,然后修改如果到达一块就直接修改像线段树一样标记,如果不到达一块就暴力修改。
就是:
“大段维护,局部朴素”——算法竞赛


code3

#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define N 100010
using namespace std;
ll a[N],sum[N],add[N];
int L[N],R[N],d;
int pos[N];
int n,m,t,l,r;
char op[3];
void change(int l,int r,long long d)
{int p=pos[l],q=pos[r];if(p==q){for(int i=l;i<=r;i++) a[i]+=d;sum[p]+=d*(r-l+1);}//全都在一块中else{for(int i=p+1;i<=q-1;i++) add[i]+=d;//维护中间段落for(int i=l;i<=R[p];i++) a[i]+=d;sum[p]+=d*(R[p]-l+1);for(int i=L[q];i<=r;i++) a[i]+=d;sum[q]+=d*(r-L[q]+1);//暴力局部修改}
}
ll ask(int l,int r)
{int p=pos[l],q=pos[r];ll ans=0;if(p==q){for(int i=l;i<=r;i++) ans+=a[i];ans+=add[p]*(r-l+1);}//全部都在一块中else{for(int i=p+1;i<=q-1;i++)ans+=sum[i]+add[i]*(R[i]-L[i]+1);//累加中间段落for(int i=l;i<=R[p];i++) ans+=a[i];ans+=add[p]*(R[p]-l+1);for(int i=L[q];i<=r;i++) ans+=a[i];ans+=add[q]*(r-L[q]+1);//暴力局部累加}return ans;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);t=sqrt(n);for(int i=1;i<=t;i++){L[i]=(i-1)*t+1;R[i]=i*t;}//标记每块左右if(R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n;//补足尾部for(int i=1;i<=t;i++)for(int j=L[i];j<=R[i];j++){pos[j]=i;//表示属于哪个块sum[i]+=a[j];//计算段落和}for(int i=1;i<=m;i++){scanf("%s %d %d",op,&l,&r);if(op[0]=='C'){scanf("%d",&d);change(l,r,d);}else printf("%lld\n",ask(l,r));}
}

POJ3468-A Simple Problem with Integers【线段树,树状数组,分块】相关推荐

  1. POJ3468 A Simple Problem with Integers【线段树 成段更新+求和 lazy标志】

    用longlong替换__int64也成. #define LL long long 输入输出用%lld Problem: 3468   User: qq1203456195 Memory: 4284 ...

  2. poj 3468 A Simple Problem with Integers(线段树区区)

    题目链接:  http://poj.org/problem?id=3468 题目大意:  给出N个数,和M次查询 C a b c  区间[a,b]的值都加上c Q a b     查询区间[a,b]值 ...

  3. POJ 3468 A Simple Problem with Integers(线段树区间更新)

    题目链接 这个真费劲...其实我也不懂 为什么...大体思想是,如果把区间更新了,开始的时候只把用懒惰标记标记那个区间,而不更新底层元素,而如果查询的时候顺带着把lz标记给消除...多敲几遍,多调试一 ...

  4. poj3468 A Simple Problem with Integers

    http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=14607 题意:题目给你n个数,m个操作,接下来一行给你这n个数,接下 ...

  5. 【线段树】【模板】讲解 + 例题1 HDU - 1754 I Hate It (点修改分数)+ 例题二 POJ - 3468 A Simple Problem with Integers(区间加值)

    [线段树][模板]讲解 + 例题1 HDU - 1754 I Hate It (点修改分数)+ 例题二 POJ - 3468 A Simple Problem with Integers(区间加值) ...

  6. poj 3243:A Simple Problem with Integers

    3243:A Simple Problem with Integers 查看 提交 统计 提示 提问 总时间限制:  5000ms  单个测试点时间限制:  2000ms  内存限制:  131072 ...

  7. A Simple Problem with Integers POJ - 3468(线段树+区间查询+区间修改+建树+懒惰标记模板)+(树状数组)

    题意: 有一个数组,有两种操作.1: Q a b 求[a,b]的和 2:C a b c 给[a,b] 的所有元素都加上c. 题目: You have N integers, A1, A2, ... , ...

  8. 【POJ - 3468 】 A Simple Problem with Integers (线段树模板 区间更新 + 区间和查询)(不能树状数组或差分数组)

    题干: You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type o ...

  9. HDU 4267 A Simple Problem with Integers [树状数组]

    根据%k=a中a和k的不同组合建立55棵树状数组,每次修改操作只对其中1棵树状数组进行操作,每次查询对其中10棵树状数组统计增量和. 1 #include <string.h> 2 #in ...

最新文章

  1. 洛谷P4316 绿豆蛙的归宿(期望)
  2. HashMap 为什么线程不安全?
  3. RHEL6.4换CentOS源
  4. 利用 .NET Framework 命令行工具
  5. mysql db compare_数据传输 | mysqldiff/mysqldbcompare 实现 DTLE 自动化测试
  6. golang中的defer
  7. 华北电力大学计算机考研大纲,2015年华北电力大学(保定)085211计算机技术考研大纲...
  8. linux如何在C程序中使用exit,c语言exit和return区别,在fork和vfork中使用
  9. 我的世界java版如何装mod_Minecraft如何安装Mod?Minecraft添加Mod的方法
  10. Spring学习总结(5)——IOC注入方式总结
  11. javaScript对象及初识面向对象
  12. MySQL 事务控制语句(TCL)
  13. 苹果电脑制作Windows U盘系统
  14. 链接mysql 504_总结403到504的常用问题
  15. ESP车身电子稳定系统
  16. AutoJs学习-动态解密
  17. java中无效字符串,在java中从字符串中删除无效的XML字符
  18. 《那些年啊,那些事——一个程序员的奋斗史》——48
  19. 传智健康2.0-6-移动端开发-体检预约
  20. 笔记本外接显示器,显示器模糊解决办法。亲测有效

热门文章

  1. java鼠标改变窗口大小监听事件_java – 当用户拖动鼠标时,监听JFrame调整事件大小?...
  2. android工程jrr版本怎么改,ionic3 生成android 如何控制versionCode版本号
  3. android bitmap string,Android Bitmap到Base64字符串(Android Bitmap to Base64 String)
  4. java 堆栈_Java中线程与堆栈的关系
  5. gif android 点击 加载,android 加载显示gif图片的解决方案
  6. mysql中有没有单行函数_MySQL之函数(单行函数、分组函数)
  7. 算法设计与分析——贪心算法——汽车加油问题
  8. LeetCode 111二叉树的最小深度-简单
  9. 计算机网络原理第一章习题3-24 3-25
  10. python注入进程_向进程中注入Python代码