题意:给出一个数列。有两个操作:1.将给定范围内的项按照顺序加上一个等差数列的项。2.求出给定范围的数列项的和。

思路1:区间更改和区间求和的操作,很容易想到了线段树。由于等差数列满足可加性(即对相同范围内的数进行两次操作1,可以看做一次操作1的和),所以必定可以用线段树。

代码如下:

#include <bits/stdc++.h>using namespace std;template<class T>
inline bool read(T &n){T x = 0, tmp = 1; char c = getchar();while ((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();if (c == EOF) return false;if (c == '-') c = getchar(), tmp = -1;while (c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar();n = x*tmp;return true;
}template <class T>
inline void write(T n) {if (n < 0) {putchar('-');n = -n;}int len = 0, data[20];while (n) {data[len++] = n % 10;n /= 10;}if (!len) data[len++] = 0;while (len--) putchar(data[len] + 48);
}typedef long long LL;const int MAXN = 101000;long long a[MAXN];
int T, M, N, Q, l, r, x, d;struct interval{int left, right, mid;long long sum, delta, x;bool lazy;
};struct SegmentTree{static const int MAX = 8 * 101000;interval node[MAX];inline int lson(int n){ return n << 1; }inline int rson(int n){ return (n << 1) | 1; }void build(int l, int r, int n){int m = (l + r) / 2;node[n].left = l;node[n].right = r;node[n].mid = m;node[n].sum = node[n].delta = node[n].x = 0LL;node[n].lazy = false;if (l == r){node[n].sum = a[l];return;}build(l, m, lson(n));build(m + 1, r, rson(n));node[n].sum += node[lson(n)].sum + node[rson(n)].sum;}void pushdown(int n){if (node[n].left == node[n].right){node[n].lazy = false;return;}//printf("[%d %d]",node[n].left,node[n].right);int l = lson(n);node[l].lazy = true;node[l].delta += node[n].delta;node[l].x += node[n].x;long long n1 = node[n].mid - node[n].left + 1;node[l].sum += node[n].x * n1 + n1 * (n1 - 1) / 2 * node[n].delta;//printf("lson: %lld ",node[l].sum);int r = rson(n);node[r].lazy = true;node[r].delta += node[n].delta;long long a1 = node[n].x + (node[n].mid - node[n].left + 1) * node[n].delta;node[r].x += a1;long long n2 = node[n].right - node[n].mid;node[r].sum += a1 * n2 + n2 * (n2 - 1) / 2 * node[n].delta;//printf("rson: %lld\n",node[r].sum);node[n].lazy = false;node[n].delta = node[n].x = 0LL;}long long sum(int l, int r, int n){if(node[n].left == node[n].right)return node[n].sum;if(l <= node[n].left && node[n].right <= r)return node[n].sum;if(node[n].lazy)pushdown(n);long long ans = 0LL;if (l <= node[n].mid)ans += sum(l, r, lson(n));if (r > node[n].mid)ans += sum(l, r, rson(n));return ans;}void modify(int l, int r, long long x, long long d, int n){if(node[n].left == node[n].right){node[n].sum += x;return;}if (l <= node[n].left && node[n].right <= r){node[n].lazy = true;node[n].delta += d;node[n].x += x;long long n1 = r - l + 1;node[n].sum += n1 * x + n1 *(n1 - 1) / 2 * d;//printf("m: %d %d\n",l,r);return;}if(node[n].lazy)pushdown(n);long long nn = r - l + 1;node[n].sum += nn * x + nn * (nn - 1) / 2 * d;if (r <= node[n].mid)modify(l, r, x, d, lson(n));else if (l > node[n].mid)modify(l, r, x, d, rson(n));else{modify(l, node[n].mid, x, d, lson(n));modify(node[n].mid + 1, r, x + (node[n].mid - l + 1) * d, d, rson(n));}}
};SegmentTree s;int main(void)
{//freopen("input.txt", "r", stdin);//freopen("out.txt", "w", stdout);read(T);while (T--){read(N), read(M);for (int i = 1; i <= N; ++i)read(a[i]);s.build(1, N, 1);for (int i = 0; i < M; ++i){read(Q), read(l), read(r);if (Q == 2)write(s.sum(l, r, 1)),puts("");else{read(x), read(d);s.modify(l, r, x, d, 1);}}}return 0;
}

思路二:由于时限是10s,可以利用复杂度为n√n的块状数组。

每个块状数组维护整体的和,和数组内所有元素对等差数列的加减(同样具有可加性)。

如果查询或者修改区间有部分无法完全包含在块状数组中,则暴力的求和和更改。

注意对数组大小的选择。过大过小都不合适。

代码如下:

#include <bits/stdc++.h>using namespace std;template<class T>
inline bool read(T &n){T x = 0, tmp = 1; char c = getchar();while ((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();if (c == EOF) return false;if (c == '-') c = getchar(), tmp = -1;while (c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar();n = x*tmp;return true;
}template <class T>
inline void write(T n) {if (n < 0) {putchar('-');n = -n;}int len = 0, data[20];while (n) {data[len++] = n % 10;n /= 10;}if (!len) data[len++] = 0;while (len--) putchar(data[len] + 48);
}const int B = 250;
const int MAX = 100100;
int T,M,N,Q;
int l,r,x,d;long long a[MAX];struct buc{long long sum;long long d,x;void clear(){sum = d = x = 0LL;}
} bucket[MAX / B];long long getsum(int l, int r){long long ans = 0;while(l < r && l % B != 0){int id = l / B;int pos = l - id * B;ans += a[l] + bucket[id].x + pos * bucket[id].d;l++;}while(l < r && r % B != 0){r--;int id = r / B;int pos = r - id * B;ans += a[r] + bucket[id].x + pos * bucket[id].d;}while(l < r){int id = l / B;ans += bucket[id].sum;l += B;}return ans;
}void update(int l,int r,long long x,long long d)
{int cnt = 0;while(l < r && l % B != 0){int id = l / B;long long aa = x + cnt * d;a[l] += aa;bucket[id].sum += aa;cnt++,l++;}while(l + B < r){int id = l / B;bucket[id].sum += B * (x + cnt * d) + B *(B - 1) / 2 * d ;bucket[id].x += x + cnt * d;bucket[id].d += d;l += B,cnt += B;}while(l < r){int id = l / B;long long aa = x + cnt * d;a[l] += aa;bucket[id].sum += aa;cnt++,l++;}
}int main(void)
{//freopen("input.txt","r",stdin);//freopen("out.txt","w",stdout);read(T);while(T--){read(N),read(M);for(int i = 0 ; i < N / B + 1; i++)bucket[i].clear();for(int i = 0 ; i< N; ++i)read(a[i]);for(int i = 0 ; i< N; ++i){int id = i / B;bucket[id].sum += a[i];}for(int i = 0; i< M; ++i){read(Q);if(Q == 2){read(l),read(r);printf("%lld\n",getsum(l-1,r));}else{read(l),read(r),read(x),read(d);update(l-1,r,(long long)x,(long long)d);}}}return 0;
}

BOJ 451 田田的算术题相关推荐

  1. BOJ 480 田田背课文

    题意:给出一个字符串,求出一个最短的只出现一次的子串的长度. 思路:利用后缀数组,我们能求得最长的重复子串.那该长度加一就是最短的只出现一次的子串的长度. 代码如下: #include <cst ...

  2. BOJ 438 田田的公司

    题意:给出n个公司和他们各自的实力值.有两种操作:合并两个公司,形成联盟.查询一个公司对应联盟的实力值的总和. 思路:裸的并查集.注意一点,可能会对已经是同一个联盟的公司再次合并,所以在合并时,需要判 ...

  3. 零起点学算法03——超简单模仿算术题

    零起点学算法03--超简单模仿算术题 Description 计算机计算能力很强哦.  让计算机帮你算其实也很容易,不过要学好计算机语言哦.  下面请看一个例子:要求计算机计算1+2的值并输出.  这 ...

  4. 451 Research发布《2019年数据中心服务和基础设施预测》

    日前,451 research 发布<2019年数据中心服务和基础设施预测>报告,对数据中心发展趋势做出5项关键预测. 趋势一 数据中心供应商将与CSP厂商加强合作 据451 resear ...

  5. 451 Sort Characters By Frequency

    451. Sort Characters By Frequency 先统计次数,再按次数构造新的string.思路没什么难,写起来还有点麻烦.用了priorityqueue.. class Wrapp ...

  6. LeetCode Algorithm 451. 根据字符出现频率排序

    451. 根据字符出现频率排序 Ideas Python解法:用个计数器,然后遍历计数器把相应字符乘以出现次数拼接起来就可以了. Code Python from collections import ...

  7. 莫队算法 BOJ 2038 [2009国家集训队]小Z的袜子(hose)

    题目传送门 1 /* 2 莫队算法:求出[l, r]上取出两只相同袜子的个数. 3 莫队算法是离线处理一类区间不修改查询类问题的算法.如果你知道了[L,R]的答案,可以在O(1)的时间下得到 4 [L ...

  8. ftp服务器上传文件提示451,解决IIS7之FTP部分文件上传451错误

    单位的需要搭建一个FTP,于是就直接使用服务器上的IIS添加了FTP组件,大家都知道IIS组件中的ftp服务器功能比较简单,但是设置起来不太个性化!配置好以后,添加一个组的用户具有上传及读取权限,使用 ...

  9. 【跃迁之路】【451天】程序员高效学习方法论探索系列(实验阶段208-2018.05.02)...

    @(跃迁之路)专栏 实验说明 从2017.10.6起,开启这个系列,目标只有一个:探索新的学习方法,实现跃迁式成长 实验期2年(2017.10.06 - 2019.10.06) 我将以自己为实验对象. ...

最新文章

  1. 鸿蒙与微信小程序,鸿蒙远程交互应用 vs 微信小程序远程交互应用
  2. Boost:assume aligned假设对齐的测试程序
  3. 训练FCN时遇到的问题总结
  4. oracle对sga统计信息不对,oracle 索引失效原因及解决方法
  5. Java进阶07 嵌套类
  6. create table as select性能测试
  7. 怎样更换UC浏览器的字体?更换UC浏览器的字体的方法
  8. mysql 与 xls 连接_数据库MySQL与xls文件的互导
  9. android camera(6)---camera2 拍照流程
  10. (转)JavaScript事件冒泡简介及应用
  11. MySQL数据库无法启动的简单排错
  12. 直通车测图需要满足哪些数据?
  13. 6轴串联关节机器人的奇异点
  14. Invalid configuration of tez jars, tez.lib.uris is not defined in the configuration
  15. ICP、PL-ICP、PP-ICP、GICP对比
  16. 情感分析(判断文章正负向)
  17. CPU与GPU区别 通俗易懂
  18. 看过千万的风景 比不上故乡的美丽
  19. 使用XML的方式导出EXCEL
  20. Symantec Backup Exec备份作业服务器盘符变更

热门文章

  1. 2022年化工自动化控制仪表最新解析及化工自动化控制仪表证考试
  2. 二十年前的互联网长啥样?还记的在网吧上hao123上面听音乐?
  3. keil8个led灯闪烁c语言程序,简单的STM32 汇编程序—闪烁LED
  4. java.io.ioexception: 你,java.io.IOException: 你的主机中的软件中止了一个已建立的连接。...
  5. ArcGIS for Desktop入门教程_第五章_ArcCatalog使用 - ArcGIS知乎-新一代ArcGIS问答社区
  6. 【数据分析与可视化】天猫直通车的部分指标解析
  7. Linux好用命令之gzip保留原文件解压缩
  8. java正则表达式 中括号_Java正则表达式获取中括号之间的内容
  9. 关于搜狗在线测评上面的题目详解
  10. 朋友圈疯传加速包抢票,还不如Python自动抢票来的靠谱!