[关闭]
@Pinetrie 2019-07-29T09:24:18.000000Z 字数 2620 阅读 797

分块及莫队题解

B - Time to Raid Cowavans

题意:给出n个数,p个询问。每个询问包含数字a、b,要求求出a,a+b,a+2b,……,a+nb的总和。
思路:对于b大于根号n的可以直接暴力,这个复杂度为s*sqrt(n)(s为这种的询问的个数)。对于b小于根号n的,可以先dp预处理出对于一个b的所有a的情况,然后o(1)询问,复杂度为n*sqrt(n)(二维dp会暴空间)。最坏情况时间复杂度为p*sqrt(n)。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn = 3 * 100010;
  5. ll w[maxn],dp[maxn],ans[maxn];
  6. ll n,p,bl;
  7. struct Ques
  8. {
  9. ll a,b,id;
  10. }q[maxn];
  11. vector<Ques>Q[maxn];
  12. int main()
  13. {
  14. scanf("%lld",&n);
  15. bl = sqrt(n);
  16. for(int i = 1;i <= n;i++) scanf("%lld",&w[i]);
  17. scanf("%lld",&p);
  18. for(int i = 1;i <= p;i++)
  19. {
  20. scanf("%lld %lld",&q[i].a,&q[i].b);
  21. q[i].id = i;
  22. if(q[i].b >= bl)
  23. {
  24. ll sum = 0;
  25. ll a = q[i].a,b = q[i].b;
  26. for(int i = a;i <= n;i += b) sum += w[i];
  27. ans[q[i].id] = sum;
  28. }
  29. else
  30. {
  31. Q[q[i].b].push_back(q[i]);
  32. }
  33. }
  34. for(int i = 1;i <= 600;i++)
  35. {
  36. for(int j = n;j >= 1;j--)
  37. {
  38. if(i + j > n) dp[j] = w[j];
  39. else dp[j] = dp[i + j] + w[j];
  40. }
  41. for(int j = 0;j < (int)Q[i].size();j++) ans[Q[i][j].id] = dp[Q[i][j].a];
  42. }
  43. for(int i = 1;i <= p;i++) printf("%lld\n",ans[i]);
  44. return 0;
  45. }

C - GukiZ and GukiZiana

题意:给出n个数,q个操作。操作一把l,r区间的所有数加x。操作二询问数组中值等于y的两个数的最大距离,如果没有则输出-1。
思路:把区间分成根号n块,让每个块内的数有序。对于修改操作,被l,r跨过的区间只需要记录一个增加值add[i],代表第i块的整体增量。未被跨过的区间不超过2*sqrt(n),可以直接直接暴力修改。对于查询操作,只需要在每块区间二分查找y值,然后更新最小、最大的下标即可。总的时间复杂度O(nlog√n + q√n * log√n)。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn = 5 * 100010;
  5. ll n,q,bl;
  6. ll add[800],a[maxn],pos[maxn];
  7. inline ll block(ll x) {return (x - 1) / bl + 1;}
  8. struct NODE
  9. {
  10. ll w,id;
  11. bool operator< (const NODE &rhs) const
  12. {
  13. return w < rhs.w;
  14. }
  15. }node[maxn];
  16. int main()
  17. {
  18. scanf("%lld %lld",&n,&q);
  19. bl = sqrt(n);
  20. for(int i = 1;i <= n;i++)
  21. {
  22. scanf("%lld",&a[i]);
  23. node[i].w = a[i];
  24. node[i].id = i;
  25. }
  26. for(int i = 1;i <= block(n);i++)
  27. {
  28. sort(node + (i - 1) * bl + 1,node + min(i * bl,n) + 1);
  29. }
  30. for(int i = 1;i <= n;i++) pos[node[i].id] = i;
  31. while(q--)
  32. {
  33. ll op,l,r,x;
  34. scanf("%lld",&op);
  35. if(op == 1)
  36. {
  37. scanf("%lld %lld %lld",&l,&r,&x);
  38. for(int i = block(l) + 1;i < block(r);i++) add[i] += x;
  39. if(block(l) < block(r))
  40. {
  41. for(int i = l;i <= block(l) * bl;i++) node[pos[i]].w += x;
  42. for(int i = (block(r) - 1) * bl + 1;i <= r;i++) node[pos[i]].w += x;
  43. sort(node + (block(l) - 1) * bl + 1,node + min(block(l) * bl,n) + 1);
  44. sort(node + (block(r) - 1) * bl + 1,node + min(block(r) * bl,n) + 1);
  45. for(int i = (block(l) - 1) * bl + 1;i <= block(l) * bl;i++) pos[node[i].id] = i;
  46. for(int i = (block(r) - 1) * bl + 1;i <= min(block(r) * bl,n);i++) pos[node[i].id] = i;
  47. }
  48. else
  49. {
  50. for(int i = l; i <= r; i++) node[pos[i]].w += x;
  51. sort(node + (block(l) - 1) * bl + 1,node + min(block(l) * bl,n) + 1);
  52. for(int i = (block(l) - 1) * bl + 1; i <= min(block(l) * bl,n); i++) pos[node[i].id] = i;
  53. }
  54. }
  55. else
  56. {
  57. struct NODE temp;
  58. scanf("%lld",&x);
  59. ll minl = maxn,maxr = 0;
  60. for(int i = 1;i <= block(n);i++)
  61. {
  62. temp.w = x - add[i];
  63. ll pl = lower_bound(node + (i - 1) * bl + 1,min(i * bl,n) + node + 1,temp) - node;
  64. ll pr = upper_bound(node + (i - 1) * bl + 1,min(i * bl,n) + node + 1,temp) - node;
  65. for(int j = pl;j < pr;j++)
  66. {
  67. minl = min(minl,node[j].id);
  68. maxr = max(maxr,node[j].id);
  69. }
  70. }
  71. if(minl == maxn && maxr == 0)
  72. printf("-1\n");
  73. else
  74. printf("%lld\n",maxr - minl);
  75. }
  76. }
  77. return 0;
  78. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注