POJ3468-A Simple Problem with Integers【线段树,树状数组,分块】
正题
题目链接:我是链接
其实洛谷线段树模板也是一样的:三种方法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,对于改写我们就将两个数组改变,然后查询就
(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【线段树,树状数组,分块】相关推荐
- POJ3468 A Simple Problem with Integers【线段树 成段更新+求和 lazy标志】
用longlong替换__int64也成. #define LL long long 输入输出用%lld Problem: 3468 User: qq1203456195 Memory: 4284 ...
- 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]值 ...
- POJ 3468 A Simple Problem with Integers(线段树区间更新)
题目链接 这个真费劲...其实我也不懂 为什么...大体思想是,如果把区间更新了,开始的时候只把用懒惰标记标记那个区间,而不更新底层元素,而如果查询的时候顺带着把lz标记给消除...多敲几遍,多调试一 ...
- poj3468 A Simple Problem with Integers
http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=14607 题意:题目给你n个数,m个操作,接下来一行给你这n个数,接下 ...
- 【线段树】【模板】讲解 + 例题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(区间加值) ...
- poj 3243:A Simple Problem with Integers
3243:A Simple Problem with Integers 查看 提交 统计 提示 提问 总时间限制: 5000ms 单个测试点时间限制: 2000ms 内存限制: 131072 ...
- 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, ... , ...
- 【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 ...
- HDU 4267 A Simple Problem with Integers [树状数组]
根据%k=a中a和k的不同组合建立55棵树状数组,每次修改操作只对其中1棵树状数组进行操作,每次查询对其中10棵树状数组统计增量和. 1 #include <string.h> 2 #in ...
最新文章
- 洛谷P4316 绿豆蛙的归宿(期望)
- HashMap 为什么线程不安全?
- RHEL6.4换CentOS源
- 利用 .NET Framework 命令行工具
- mysql db compare_数据传输 | mysqldiff/mysqldbcompare 实现 DTLE 自动化测试
- golang中的defer
- 华北电力大学计算机考研大纲,2015年华北电力大学(保定)085211计算机技术考研大纲...
- linux如何在C程序中使用exit,c语言exit和return区别,在fork和vfork中使用
- 我的世界java版如何装mod_Minecraft如何安装Mod?Minecraft添加Mod的方法
- Spring学习总结(5)——IOC注入方式总结
- javaScript对象及初识面向对象
- MySQL 事务控制语句(TCL)
- 苹果电脑制作Windows U盘系统
- 链接mysql 504_总结403到504的常用问题
- ESP车身电子稳定系统
- AutoJs学习-动态解密
- java中无效字符串,在java中从字符串中删除无效的XML字符
- 《那些年啊,那些事——一个程序员的奋斗史》——48
- 传智健康2.0-6-移动端开发-体检预约
- 笔记本外接显示器,显示器模糊解决办法。亲测有效
热门文章
- java鼠标改变窗口大小监听事件_java – 当用户拖动鼠标时,监听JFrame调整事件大小?...
- android工程jrr版本怎么改,ionic3 生成android 如何控制versionCode版本号
- android bitmap string,Android Bitmap到Base64字符串(Android Bitmap to Base64 String)
- java 堆栈_Java中线程与堆栈的关系
- gif android 点击 加载,android 加载显示gif图片的解决方案
- mysql中有没有单行函数_MySQL之函数(单行函数、分组函数)
- 算法设计与分析——贪心算法——汽车加油问题
- LeetCode 111二叉树的最小深度-简单
- 计算机网络原理第一章习题3-24 3-25
- python注入进程_向进程中注入Python代码