内存限制:256 MiB时间限制:500 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: hzwer

题目描述

给出一个长为 nn 的数列 a_1\ldots a_na1​…an​,以及 nn 个操作,操作涉及区间开方,区间求和。

输入格式

第一行输入一个数字 nn。

第二行输入 nn 个数字,第 ii 个数字为 a_iai​,以空格隔开。

接下来输入 nn 行询问,每行输入四个数字 \mathrm{opt}, l, r, copt,l,r,c,以空格隔开。

若 \mathrm{opt} = 0opt=0,表示将位于 [l, r][l,r] 的之间的数字都开方。对于区间中每个 a_i(l\le i\le r),\: a_i ← \left\lfloor \sqrt{a_i}\right\rfloorai​(l≤i≤r),ai​←⌊ai​​⌋

若 \mathrm{opt} = 1opt=1,表示询问位于 [l, r][l,r] 的所有数字的和。

输出格式

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

样例

样例输入

  1. 4
  2. 1 2 2 3
  3. 0 1 3 1
  4. 1 1 4 4
  5. 0 1 2 2
  6. 1 1 2 4

样例输出

  1. 6
  2. 2

数据范围与提示

对于 100\%100% 的数据,1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、\mathrm{ans} \leq 2^{31}-1ans≤231−1。

代码一:

  1. //#6281. 数列分块入门 5-区间开方,区间求和
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. typedef long long ll;
  5. const int maxn=5e4+;
  6.  
  7. int n,m,pos[maxn],tag[maxn];
  8. ll a[maxn],b[maxn];
  9.  
  10. void rechange(int x)
  11. {
  12. int flag=;
  13. for(int i=(x-)*m+;i<=min(x*m,n);i++){
  14. if(a[i]>) flag=;
  15. }
  16. if(!flag) tag[x]=;
  17. }
  18.  
  19. void update(int l,int r)
  20. {
  21. if(pos[l]==pos[r]){
  22. if(tag[pos[l]]){
  23. for(int i=l;i<=r;i++){
  24. b[pos[l]]-=a[i];
  25. a[i]=floor(sqrt(a[i]));
  26. b[pos[l]]+=a[i];
  27. }
  28. rechange(pos[l]);
  29. }
  30. }
  31. else{
  32. if(tag[pos[l]]){
  33. for(int i=l;i<=pos[l]*m;i++){
  34. b[pos[l]]-=a[i];
  35. a[i]=floor(sqrt(a[i]));
  36. b[pos[l]]+=a[i];
  37. }
  38. rechange(pos[l]);
  39. }
  40. for(int i=pos[l]+;i<pos[r];i++){
  41. if(!tag[i]) continue;
  42. for(int j=(i-)*m+;j<=i*m;j++){
  43. b[i]-=a[j];
  44. a[j]=floor(sqrt(a[j]));
  45. b[i]+=a[j];
  46. }
  47. rechange(i);
  48. }
  49. if(tag[pos[r]]){
  50. for(int i=(pos[r]-)*m+;i<=r;i++){
  51. b[pos[r]]-=a[i];
  52. a[i]=floor(sqrt(a[i]));
  53. b[pos[r]]+=a[i];
  54. }
  55. rechange(pos[r]);
  56. }
  57. }
  58. }
  59.  
  60. ll query(int l,int r)
  61. {
  62. ll ans=;
  63. if(pos[l]==pos[r]){
  64. for(int i=l;i<=r;i++){
  65. ans+=a[i];
  66. }
  67. }
  68. else{
  69. for(int i=l;i<=pos[l]*m;i++){
  70. ans+=a[i];
  71. }
  72. for(int i=pos[l]+;i<pos[r];i++){
  73. ans+=b[i];
  74. }
  75. for(int i=(pos[r]-)*m+;i<=r;i++){
  76. ans+=a[i];
  77. }
  78. }
  79. return ans;
  80. }
  81.  
  82. int main()
  83. {
  84. scanf("%d",&n);
  85. m=sqrt(n);
  86. for(int i=;i<=n;i++){
  87. scanf("%lld",&a[i]);
  88. pos[i]=(i-)/m+;
  89. }
  90. for(int i=;i<=n;i++){
  91. int cnt=log(a[i])/log();
  92. if(cnt>=) tag[pos[i]]=;
  93. }
  94. for(int i=;i<=m+;i++){
  95. ll cnt=;
  96. for(int j=(i-)*m+;j<=min(i*m,n);j++){
  97. cnt+=a[j];
  98. }
  99. b[i]=cnt;
  100. }
  101. for(int i=;i<=n;i++){
  102. int op,l,r,c;
  103. scanf("%d%d%d%d",&op,&l,&r,&c);
  104. if(op==){
  105. update(l,r);
  106. }
  107. else{
  108. printf("%lld\n",query(l,r));
  109. }
  110. }
  111. }
  112.  
  113. /*
  114. 10
  115. 1 3 4 2 5 7 11 3 5 1
  116. 0 1 5 1
  117. 1 1 7 2
  118. 0 3 9 1
  119. 1 4 8 7
  120. 1 1 10 6
  121. 1 3 5 3
  122. 1 5 10 7
  123. 1 6 10 6
  124. 1 2 7 4
  125. 1 3 7 5
  126.  
  127. 25
  128. 8
  129. 14
  130. 3
  131. 10
  132. 9
  133. 9
  134. 8
  135. */

代码二:

  1. //#6281. 数列分块入门 5-区间开方,区间求和(忘注释掉了,导致超时+wa,蠢死了)
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. typedef long long ll;
  5. const int maxn=5e4+;
  6.  
  7. int n,m,pos[maxn],tag[maxn];
  8. ll a[maxn],b[maxn];
  9.  
  10. void rechange(int x)
  11. {
  12. ll cnt=;int flag=;
  13. for(int i=(x-)*m+;i<=min(x*m,n);i++){
  14. cnt+=a[i];
  15. if(a[i]>=) flag=;
  16. }
  17. b[x]=cnt;
  18. if(!flag) tag[x]=;
  19. }
  20.  
  21. void update(int l,int r)
  22. {
  23. if(pos[l]==pos[r]){
  24. if(tag[pos[l]]){
  25. for(int i=l;i<=r;i++){
  26. a[i]=floor(sqrt(a[i]));
  27. }
  28. rechange(pos[l]);
  29. }
  30. }
  31. else{
  32. if(tag[pos[l]]){
  33. for(int i=l;i<=pos[l]*m;i++){
  34. a[i]=floor(sqrt(a[i]));
  35. }
  36. rechange(pos[l]);
  37. }
  38. for(int i=pos[l]+;i<pos[r];i++){
  39. if(!tag[i]) continue;
  40. for(int j=(i-)*m+;j<=i*m;j++){
  41. a[j]=floor(sqrt(a[j]));
  42. }
  43. rechange(i);
  44. }
  45. if(tag[pos[r]]){
  46. for(int i=(pos[r]-)*m+;i<=r;i++){
  47. a[i]=floor(sqrt(a[i]));
  48. }
  49. rechange(pos[r]);
  50. }
  51. }
  52. }
  53.  
  54. ll query(int l,int r)
  55. {
  56. ll ans=;
  57. if(pos[l]==pos[r]){
  58. for(int i=l;i<=r;i++){
  59. ans+=a[i];
  60. }
  61. }
  62. else{
  63. for(int i=l;i<=pos[l]*m;i++){
  64. ans+=a[i];
  65. }
  66. for(int i=pos[l]+;i<pos[r];i++){
  67. ans+=b[i];
  68. }
  69. for(int i=(pos[r]-)*m+;i<=r;i++){
  70. ans+=a[i];
  71. }
  72. }
  73. //cout<<"ans: "<<ans<<endl;
  74. return ans;
  75. }
  76.  
  77. int main()
  78. {
  79. scanf("%d",&n);
  80. m=sqrt(n);
  81. for(int i=;i<=n;i++){
  82. scanf("%lld",&a[i]);
  83. pos[i]=(i-)/m+;
  84. }
  85. for(int i=;i<=n;i++){
  86. int cnt=log(a[i])/log();
  87. if(cnt>=) tag[pos[i]]=;
  88. }
  89. for(int i=;i<=m+;i++){
  90. ll cnt=;
  91. for(int j=(i-)*m+;j<=min(i*m,n);j++){
  92. cnt+=a[j];
  93. }
  94. b[i]=cnt;
  95. }
  96. for(int i=;i<=n;i++){
  97. int op,l,r,c;
  98. scanf("%d%d%d%d",&op,&l,&r,&c);
  99. if(op==){
  100. update(l,r);
  101. // for(int i=1;i<=n;i++)
  102. // cout<<a[i]<<" ";
  103. // cout<<endl;
  104. }
  105. else{
  106. printf("%lld\n",query(l,r));
  107. }
  108. }
  109. }
  110.  
  111. /*
  112. 10
  113. 1 3 4 2 5 7 11 3 5 1
  114. 0 1 5 1
  115. 1 1 7 2
  116. 0 3 9 1
  117. 1 4 8 7
  118. 1 1 10 6
  119. 1 3 5 3
  120. 1 5 10 7
  121. 1 6 10 6
  122. 1 2 7 4
  123. 1 3 7 5
  124.  
  125. 25
  126. 8
  127. 14
  128. 3
  129. 10
  130. 9
  131. 9
  132. 8
  133. */

LOJ #6281. 数列分块入门 5-分块(区间开方、区间求和)的更多相关文章

  1. 线段树 区间开方区间求和 & 区间赋值、加、查询

    本文同步发表于 https://www.zybuluo.com/Gary-Ying/note/1288518 线段树的小应用 -- 维护区间开方区间求和 题目传送门 约定: sum(i,j) 表示区间 ...

  2. LOJ 6281 数列分块入门 5

    简化版题意 给出一个长为n的数列,以及n个操作,操作涉及区间开方(每个数都向下取整),区间求和,保证所有数都为有符号32位正整数. N<=50000 Solution 首先我们先思考: 一个有符 ...

  3. LibreOJ 6281 数列分块入门 5(分块区间开方区间求和)

    题解:区间开方emmm,这马上让我想起了当时写线段树的时候,很显然,对于一个在2^31次方以内的数,开方7-8次就差不多变成一了,所以我们对于每次开方,如果块中的所有数都为一了,那么开方也没有必要了. ...

  4. LOJ.6281.数列分块入门5(分块 区间开方)

    题目链接 int内的数(也不非得是int)最多开方4.5次就变成1了,所以还不是1就暴力,是1就直接跳过. #include <cmath> #include <cstdio> ...

  5. [Libre 6281] 数列分块入门 5 (分块)

    水一道入门分块qwq 题面:传送门 开方基本暴力.. 如果某一个区间全部都开成1或0就打上标记全部跳过就行了 因为一个数开上个四五六次就是1了所以复杂度能过233~ code: //By Menteu ...

  6. LibreOJ 6280 数列分块入门 4(分块区间加区间求和)

    题解:分块的区间求和比起线段树来说实在是太好写了(当然,复杂度也高)但这也是没办法的事情嘛.总之50000的数据跑了75ms左右还是挺优越的. 比起单点询问来说,区间询问和也没有复杂多少,多开一个su ...

  7. LOJ.6284.数列分块入门8(分块)

    题目链接 \(Description\) 给出一个长为n的数列,以及n个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c. \(Solution\) 模拟一些数据可以发现,询问后 ...

  8. LibreOJ 6277 数列分块入门 1(分块)

    题解:感谢hzwer学长和loj让本蒟蒻能够找到如此合适的入门题做. 这是一道非常标准的分块模板题,本来用打标记的线段树不知道要写多少行,但是分块只有这么几行,极其高妙. 代码如下: #include ...

  9. LibreOJ 6278 数列分块入门 2(分块)

     题解:非常高妙的分块,每个块对应一个桶,桶内元素全部sort过,加值时,对于零散块O(sqrt(n))暴力修改,然后暴力重构桶.对于大块直接整块加.查询时对于非完整块O(sqrt(n))暴力遍历.对 ...

随机推荐

  1. synchronize 和volatile 实现共享变量在多线程中的可见性

    1.什么是线程可见性 可见性:一个线程对共享变量值的修改能够及时被其他线程看到. 共享变量:如果一个变量在多个线程工作内存中都存在副本,那么着给按量就是这几个线程的共享变量. 2.导致共享变量在线程间 ...

  2. jquery动画切换引擎插件 Velocity.js 学习02

    案例实践: 第一页会以动画形式进入页面: 点击进入按钮时,第一页以动画消失,第二页以动画形式进入,同时四张图片也定义从小到大的动画形式: 第二页关闭按钮点击时,先是四张图片以缩小动画消失,然后第二页以 ...

  3. MySQL查看所有用户及拥有权限

    查看MYSQL数据库中所有用户 mysql> SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM m ...

  4. jQuery简单的Ajax调用

    index.php 的代码如下: <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"& ...

  5. Golang向Templates 插入对象的值

    Go对象可以插入到template中,然后把对象的值表现在template中,你可以一层层的分解这个对象,去找他的子字段,当前对象用'.'来表示,所以当当前对象是一个string的时候,你可以用{{. ...

  6. 求逆元的两种方法+求逆元的O(n)递推算法

    到国庆假期都是复习阶段..所以把一些东西整理重温一下. gcd(a,p)=1,ax≡1(%p),则x为a的逆元.注意前提:gcd(a,p)=1; 方法一:拓展欧几里得 gcd(a,p)=1,ax≡1( ...

  7. bzoj 2705: [SDOI2012]Longge的问题——欧拉定理

    Description Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题.现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N). Input 一 ...

  8. js_setCookie,getCookie和checkcookie函数

    随便说说: cookie和sessionStrong,localStrong在web应用中都有一种存储的功能,也就是说可以把一些数据记录在浏览器.cookie和后两者的主要区别 是cookie是和后端 ...

  9. new操作符(翻译自mozilla.org)

    翻译自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new new操作符可以实例化一个用户自 ...

  10. eclipse执行maven install命令时跳过test

    在pom.xml里面配置一下代码,将跳过test. <plugins> <plugin> <groupId>org.apache.maven.plugins< ...