给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。

2、“Q l r”,表示询问 A[l],A[l+1],…,A[r] 的最大公约数(GCD)。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数N,M。

第二行N个整数A[i]。

接下来M行表示M条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

N≤500000,M≤100000N≤500000,M≤100000

输入样例:

  1. 5 5
  2. 1 3 5 7 9
  3. Q 1 5
  4. C 1 5 1
  5. Q 1 5
  6. C 3 3 6
  7. Q 2 4

输出样例:

  1. 1
  2. 2
  3. 4

算法:线段树 + 增量数组(树状数组) + 差分序列

题解:

  性质:

  • gcd(a, b) = gcd(a, b - a)
  • gcd(a, b, c) = gcd(a, b - a, c - b)
  • acd(a1, a2, ... , an) = gcd(a1, a2 - a1, ... , an - an-1)

  利用这条性质来求解此题

  1. 对用询问“Q l r”来说,可以求出结果__gcd(arr[l], query(1, l + 1, r),就是同上面的性质,前面那个arr[l]就是性质里面的第一个数,后面的就是存在了线段树里面差分序列,求出(l + 1, r)区间的最大公约数即可。(其中的arr[l]等于原本数组里面的值加上后面更改的值,更改的值记录再树状数组里面)。
  2. 对于询问“C l r d”来说,只需要修改树状数组里面的值,以及线段树里面的值即可。

注意:题目会爆int,需要用long long。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5.  
  6. using namespace std;
  7.  
  8. typedef long long ll;
  9.  
  10. const int maxn = 5e5+;
  11.  
  12. struct node {
  13. ll l, r;
  14. ll dat;
  15. }tree[maxn << ]; //维护差分序列的线段树
  16.  
  17. ll n, m;
  18. ll d[maxn]; //差分数组
  19. ll arr[maxn]; //原始数组
  20. ll T[maxn]; //增量数组(树状数组)
  21.  
  22. ll lowbit(ll x) {
  23. return x & (-x);
  24. }
  25.  
  26. void pushup(ll root) {
  27. tree[root].dat = __gcd(tree[root << ].dat, tree[root << | ].dat);
  28. }
  29.  
  30. void build(ll root, ll l, ll r) {
  31. tree[root].l = l;
  32. tree[root].r = r;
  33. if(l == r) {
  34. tree[root].dat = d[l];
  35. return;
  36. }
  37. ll mid = (l + r) >> ;
  38. build(root << , l, mid);
  39. build(root << | , mid + , r);
  40. pushup(root);
  41. }
  42.  
  43. void add(ll x, ll val) {
  44. while(x <= n) {
  45. T[x] += val;
  46. x += lowbit(x);
  47. }
  48. }
  49.  
  50. ll ask(ll x) {
  51. ll res = ;
  52. while(x > ) {
  53. res += T[x];
  54. x -= lowbit(x);
  55. }
  56. return res;
  57. }
  58.  
  59. void update(ll root, ll pos, ll val) {
  60. ll l = tree[root].l;
  61. ll r = tree[root].r;
  62. if(l == r) {
  63. tree[root].dat += val;
  64. return;
  65. }
  66. ll mid = (l + r) >> ;
  67. if(pos <= mid) {
  68. update(root << , pos, val);
  69. } else {
  70. update(root << | , pos, val);
  71. }
  72. pushup(root);
  73. }
  74.  
  75. ll query(ll root, ll x, ll y) {
  76. ll l = tree[root].l;
  77. ll r = tree[root].r;
  78. if(x <= l && r <= y) {
  79. return tree[root].dat;
  80. }
  81. ll mid = (l + r) >> ;
  82. ll res = ;
  83. if(x <= mid) {
  84. res = __gcd(res, query(root << , x, y));
  85. }
  86. if(y > mid) {
  87. res = __gcd(res, query(root << | , x, y));
  88. }
  89. return abs(res); //注意:这里需要加绝对值,因为可能出现负数
  90. }
  91.  
  92. int main() {
  93. scanf("%lld%lld", &n, &m);
  94. for(ll i = ; i <= n; i++) {
  95. scanf("%lld", &arr[i]);
  96. d[i] = arr[i] - arr[i - ]; //构建差分数组
  97. }
  98. build(, , n);
  99. while(m--) {
  100. char str[];
  101. ll l, r, val;
  102. scanf("%s", str);
  103. if(str[] == 'Q') {
  104. scanf("%lld %lld", &l, &r);
  105. ll now = arr[l] + ask(l); //获取当前位置的值(原始数组 + 增量数组)
  106. printf("%lld\n", __gcd(now, query(, l + , r))); //与后面的部分求最大公约数
  107. } else {
  108. scanf("%lld %lld %lld", &l, &r, &val);
  109. add(l, val);
  110. add(r + , -val);
  111. update(, l, val);
  112. if(r < n) { //判断是否会越界
  113. update(, r + , -val);
  114. }
  115.  
  116. }
  117. }
  118. return ;
  119. }

AcWing:246. 区间最大公约数(线段树 + 增量数组(树状数组) + 差分序列)的更多相关文章

  1. AcWing 246. 区间最大公约数

    246. 区间最大公约数 思路: 首先根据更相减损术,我们得到一个结论: \(gcd(a_l, a_{l+1}, ...,a_r) = gcd(a_l, a_{l+1}-a_l, a_{l+2}-a_ ...

  2. 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询

    题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...

  3. [bzoj3155]Preprefix sum(树状数组)

    3155: Preprefix sum Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 1183  Solved: 546[Submit][Status] ...

  4. Codeforces 980E The Number Games - 贪心 - 树状数组

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...

  5. 1082 线段树练习 3 && 树状数组区间修改区间查询

    1082 线段树练习 3 题意: 给定序列初值, 要求支持区间修改, 区间查询 Solution 用树状数组, 代码量小, 空间占用小 巧用增量数组, 修改时在 \(l\) 处 $ + val$ , ...

  6. acwing 243. 一个简单的整数问题2 树状数组 线段树

    地址 https://www.acwing.com/problem/content/description/244/ 给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l ...

  7. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

  8. NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)

    Problem 1050: Just Go Time Limits:  3000 MS   Memory Limits:  65536 KB 64-bit interger IO format:  % ...

  9. POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)

    题意: 有一个n*n的矩阵,初始化全部为0.有2中操作: 1.给一个子矩阵,将这个子矩阵里面所有的0变成1,1变成0:2.询问某点的值 方法一:二维线段树 参考链接: http://blog.csdn ...

随机推荐

  1. 使用Redis實現秒殺功能

    <?php $id = 1; $pdo=new PDO("mysql:host=127.0.0.1;dbname=test","root","r ...

  2. 01:keepalive高可用集群

    1.1 keepalived高可用软件介绍 1.keepalived--监控检查 注:keepalive软件有两种功能:监控检查.VRRP冗余协议 1. keepalive的作用是检测web服务器的状 ...

  3. 学习python基础规则

    前面应该是记流水账的方式,毕竟学习的内容不多无法产出什么有效的内容. 这两天从开始下载Python开始学习,一路顺畅冒的问题,直到开始学习python的游戏规则,严格缩进.注释及‘’的使用等感觉还不错 ...

  4. 分布式锁的几种实现方法:redis实现分布式锁

    使用失效的方式实现分布式锁(推荐) import redis.clients.jedis.Jedis; /** * 使用redis实现分布式锁(推荐) * */ public class JedLoc ...

  5. java实现的LinkedLilst

    package javabean.adt.List; import java.util.ConcurrentModificationException; import java.util.Iterat ...

  6. bash脚本测试总结

    bash脚本测试总结   跟踪脚本的执行 可以让bash打印出你脚本执行的过程中的所有语句.这很简单,只需要使用bash的-x选项就可以做到,下面让我们来看一下.   下面的这段脚本,先是输出一个问候 ...

  7. snappy-java两种压缩方式的区别

    1.Snappy-java项目地址 https://github.com/xerial/snappy-java 2.Snappy-java两种压缩方式 使用Snappy.compress进行压缩 St ...

  8. feign 多参数问题

    参考: https://stackoverflow.com/questions/43604734/springboot-feignclient-method-has-too-many-paramter ...

  9. Elasticsearch 7.4.0官方文档操作

    官方文档地址 https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 1.0.0 设置Elasticsea ...

  10. HackIM web关writeup

    Web100 访问页面将看到下面的错误 在burp里使用request / response查看有没有什么不正常的地方.如下图所示,在返回的数据包里被设置了两次不同的PHPSESSID. 如果我把PH ...