Acwing 243

输入样例:

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

输出样例:

4
55
9
15

树状数组做法

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=200010;ll a[N],c[2][N],sum[N],n,m;ll ask(int k,int x){ll ans=0;for(;x;x-=lowbit(x)) ans+=c[k][x];return ans;
}
void add(int k,int x,int y){for(;x<=n;x+=lowbit(x)) c[k][x]+=y;
}int main(){ios::sync_with_stdio(false); cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i];while(m--){char ch;cin>>ch;if(ch=='C'){int l,r,d;cin>>l>>r>>d;add(0,l,d);add(0,r+1,-d);add(1,l,l*d);add(1,r+1,-d*(r+1));}else{int x,y;cin>>x>>y;ll res=sum[y]+(y+1)*ask(0,y)-ask(1,y) - (sum[x-1]+x*ask(0,x-1)-ask(1,x-1));cout<<res<<endl;}} return 0;
} 作者:拓海
链接:https://www.acwing.com/activity/content/code/content/1763390/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

线段树做法

线段树每个节点保存 l 、r、sum(区间和) 、add(增量延迟标记)
spread 函数实现了延迟标记的向下传递

#include<bits/stdc++.h>
#define ll long long
using namespace std;const int N=1e5+10;
int a[N],n,m;struct ST{int l,r;ll sum,add;
}t[N*4];void build(int p,int l,int r){t[p].l = l,t[p].r = r;//p 节点代表区间[l,r] if(l==r) {t[p].sum = a[l];return ;//到叶节点 }int mid = (l+r)/2;//折半 build(p*2,l,mid); //左子节点[l,mid] 编号2*p build(p*2+1,mid+1,r); //右子节点[mid+1,r] 编号2*p+1  t[p].sum=t[p*2].sum + t[p*2+1].sum;
}
void spread(int p){if(t[p].add){t[p*2].sum += t[p].add*(t[p*2].r - t[p*2].l+1);//更新左子节点 t[p*2+1].sum += t[p].add*(t[p*2+1].r - t[p*2+1].l+1);//更新右子节点t[p*2].add +=  t[p].add;//给左子节点打延迟标记 t[p*2+1].add +=  t[p].add;//给右子节点打延迟标记t[p].add = 0;//清除节点p的标记 }
}
void change(int p,int l,int r,int d){if( l<=t[p].l && r>=t[p].r){ //完全覆盖 t[p].sum += (ll)d*(t[p].r-t[p].l+1); //更新节点信息 t[p].add += d; //给节点打延迟标记 return ;}spread(p); int mid=(t[p].l + t[p].r)/2;if(l<=mid) change(p*2, l, r, d);// x 属于左半区间 if(r>mid) change(p*2+1, l, r, d);  // x 属于右半区间 t[p].sum = t[p*2].sum + t[p*2+1].sum;
}ll ask(int p,int l,int r){if(l<=t[p].l && r>=t[p].r) return t[p].sum;//完全包含 spread(p);int mid = (t[p].l + t[p].r) / 2;ll val = 0;   //负无穷大 if(l<=mid) val += ask(p*2,l,r);// 左子节点有重叠 if(r>mid) val += ask(p*2+1,l,r);// 右子节点有重叠 return val;
} int main(){ios::sync_with_stdio(false);cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);while(m--){char ch;int l,r,d;cin>>ch>>l>>r;if(ch=='C'){cin>>d;change(1,l,r,d);}  else cout<<ask(1,l,r)<<endl;}return 0;
}

分块做法


#include<bits/stdc++.h>
#define ll long long
#define ini(a)      memset(a,0,sizeof(a))
#define ini2(a,b)   memset(a,b,sizeof(a))
using namespace std;const int N=100010; ll a[N],sum[N],add[N];
int L[N],R[N];
int pos[N];
int n,m,t;void change(ll l, ll r, ll d) {ll p = pos[l], q = pos[r];if (p == q) {for (ll i=l; i<=r; i++) a[i]+=d;sum[p] += d*(r-l+1);} else {//和上面类似 for (ll i=l; i<=R[p]; i++) a[i] += d;sum[p] += d*(R[p]-l+1);for (ll i=L[q]; i<=r; i++) a[i] += d;sum[q] += d*(r-L[q]+1);for (ll i=p+1; i<=q-1; i++) add[i] += d;}
}ll ask(ll l, ll r) {ll ans = 0;ll p = pos[l], q = pos[r];if (p == q) {for (ll i=l; i<=r; i++) {ans += a[i];}ans += add[q]*(r-l+1);} else {for (ll i=l; i<=R[p]; i++) ans += a[i];ans += add[p]*(R[p]-l+1);for (ll i=L[q]; i<=r; i++) ans += a[i];ans += add[q]*(r-L[q]+1);for (ll i=p+1; i<=q-1; i++) {ans += add[i] * (R[i]-L[i]+1);ans += sum[i];}}return ans;
}void solve() {cin>>n>>m;for (ll i=1; i<=n; i++) cin>>a[i];//分块 t = sqrt(n);for (ll 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;//最后一段处理 //预处理ini(sum), ini(add);for (ll i=1; i<=t; i++) {for (ll j=L[i]; j<=R[i]; j++) {pos[j] = i;//属于第几段sum[i] += a[j]; }}//指令for (ll i=1; i<=m; i++) {char ch;ll l, r, d;cin>>ch>>l>>r;if (ch == 'C') {cin>>d;change(l, r, d);} else {cout<<ask(l, r)<<endl;}}
}int main()
{solve();return 0;
}

树状数组、线段树、分块 在同一题目中的应用(Acwing 243)相关推荐

  1. D-query SPOJ - DQUERY(求区间不同数的个数)(树状数组||线段树+离散)(主席树+在线)

    English Vietnamese Given a sequence of n numbers a1, a2, -, an and a number of d-queries. A d-query ...

  2. HDU 1556 前缀和 树状数组 线段树

    解法一: a[i]表示以 i作为起点,对 i-n的气球全部上色的次数  对(start,end)区间上色 ++a[start] --a[end+1]抵消掉 end+1-n的部分 问题转换为求 a的前缀 ...

  3. jzoj3854-分组【树状数组,线段树】

    正题 题目链接:https://jzoj.net/senior/#contest/show/2990/2 题目大意 一个小队满足要求 队长的地位最高 所有队员和队长的年龄差不超过kkk 给出nnn个人 ...

  4. 模板三连击:树状数组+线段树+主席树

    没事儿干,复习模板...... 1.树状数组 本来不想写这个的,但是反正就几分钟就打完了,所以就写了,水AC数. 洛谷 P3374 [模板]树状数组 1 1 #include<cstdio> ...

  5. 51nod 1680区间求和 (dp+树状数组/线段树)

    不妨考虑已知一个区间[l,r]的k=1.k=2....k=r-l+1这些数的答案ans(只是这一个区间,不包含子区间) 那么如果加入一个新的数字a[i](i = r+1) 则新区间[l, i]的答案为 ...

  6. CCF201709-5 除法(100分)【树状数组+线段树】

    试题编号: 201709-5 试题名称: 除法 时间限制: 10.0s 内存限制: 256.0MB 问题描述: 问题描述 小葱喜欢除法,所以他给了你N个数a1, a2, ⋯, aN,并且希望你执行M次 ...

  7. POJ2182 HDU2711 Lost Cows【树状数组+线段树】

    Lost Cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17113 Accepted: 10664 Descripti ...

  8. P2357 守墓人(树状数组/线段树)

    题目描述 在一个荒凉的墓地上 有一个令人尊敬的守墓人, 他看守的墓地从来 没有被盗过, 所以人们很放心的把自己的先人的墓 安顿在他那 守墓人能看好这片墓地是必然而不是偶然..... 因为....守墓人 ...

  9. 差分+树状数组 线段树【P2357】 守墓人

    题目描述-->p2357 守墓人 敲了一遍线段树,水过. 树状数组分析 主要思路: 差分 简单介绍一下差分(详细概念太麻烦,看下面. 给定一个数组 7 8 6 5 1 8 18 20 35 // ...

最新文章

  1. 配置apache+php环境详解
  2. python关键字列表的表达式,python 列表推导和生成器表达式的使用
  3. qt 从文件中读出数据显示在表格中_QT中有什么控件可以实现向excel的表格显示,qt数据存储到Excel表格...
  4. Method Swizzle黑魔法,修改 ios 系统类库方法(转载)
  5. 【操作系统】内存的分页管理与分段管理の异同
  6. 虚拟服务器声卡,如何使用虚拟声卡?虚拟声卡安装教程!
  7. windos下安装redis
  8. ubantu 添加防火墙策略_Ubuntu防火墙安装和配置
  9. c语言if的时候自动转换,[求助]IF语句转换SWITCH语句写出!如何
  10. 2021-2025年中国一次性马桶马桶座套行业市场供需与战略研究报告
  11. Debug日志正常,输出和HTML页面乱码
  12. 二十五、JAVA多线程(五、线程生命周期)
  13. 一些比较舒服的rgb配色 (含rgb值,可参考)
  14. 随机划分训练集和测试集
  15. MFC控件学习:图片(bmp/png)
  16. 解析身份证号码(附加Java代码)
  17. 【Android】canScrollVertically和canScrollHorizontally
  18. spring AspectJ的Execution表达式expression
  19. Ubuntu16.04下gdb工具gef的安装 wget命令详解
  20. html5弹页面腮红,腮红总是打的很奇怪 这里有画腮红的小技巧

热门文章

  1. python+pyautogui+pyperclip实现QQ自动加好友功能
  2. phpwind安装空白问题解决
  3. 第四周web课堂作业
  4. 【JavaWeb】实现网页验证码
  5. 新浪开发者平台(Sina App Engine)初探
  6. python中test是什么意思_Python unittest 之一: 什么是单元测试
  7. OpenGL 渐变色背景
  8. 技术人员的狂欢 | 看雪2020第四届安全开发者峰会顺利落幕
  9. LPC2141芯片解密 芯片解密干什么
  10. 关于SASL的介绍文档