把自己去年在luogu写的一个题解搬过来

原题解链接

1. 题目大意

给定一个长度为 \(n\) 的数列 \(a_1,a_2,a_3,...,a_n\) , 并给出 \(m\) 个操作,操作类型如下:

操作1:查询区间最大值,输出最大值与 \(a_1\) 的差;

操作2:交换两个数的位置;

操作3:选择一段区间 \([l,r]\) 并给定 \(t\) ,将区间中第 \(x\) 个数加上 $x\cdot t $ .

\(n,m \le 10^5\) .

2. 解题报告

本题的正解是分块。

首先我们先考虑操作3,对于两边的元素,我们直接暴力修改然后重构即可。那么我们如何维护整块呢?

维护 \(add[ x ]\) 表示第 \(x\) 块累加的 \(t\) , 那我们要得到单个元素,再维护一个偏移量 \(del[x]\) ,这样块中元素的权值即可表示为 \(w[i]=a[i]+add[x]\times i-del[x]\).

(举个例子,若给块 \([4,6]\) 加上 \(2T, 3T, 4T\) ,那么\(add[x]=T\) ,\(del[x]=2T\),这样 \(w[5]=a[5]+5T-2T=a[5]+3T\) .)

对于操作2,我们直接暴力交换然后重构块即可。

对于操作1,我们考虑在整块被修改后,如何维护块内的最大值。由于每个元素的编号 \(i\) 和权值 \(a_i\) 都是定值且 \(i\) 单增,我们可以将每个元素看成 \((i,a_i)\) ,然后用单调栈维护一个上凸壳。这样随着 \(add\) 的增大,最大元素位置一定向右移动,且元素权值呈单峰。

每个操作维护(询问)的复杂度都为 \(O( n\sqrt{n} )\),再加上本题时间限制宽松,可以轻松通过。

3. 参考程序

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. namespace io {
  5. const int SIZE=(1<<21)+1;
  6. char ibuf[SIZE],*iS,*iT;
  7. char gc()
  8. {
  9. if(iS==iT) iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin);
  10. if(iS==iT) return EOF;
  11. return *iS++;
  12. }
  13. inline int gi()
  14. {
  15. char c; int x=0,f=1;
  16. for(;c<'0'||c>'9';c=gc())if(c=='-')f=-1;
  17. for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+c-'0';
  18. return x*f;
  19. }
  20. }
  21. using io::gi;
  22. const int N=100005,qN=320;
  23. int n,m,bel[N],b,s[qN][qN],tp[qN],pos[qN];
  24. ll h[N],a[N],add[qN],del[qN];
  25. #define top s[x][tp[x]]
  26. #define dtp s[x][tp[x]-1]
  27. #define Max(x) s[x][pos[x]]
  28. void remove(int x)
  29. {
  30. for(int i=(x-1)*b+1;i<=x*b;i++) a[i]+=add[x]*i-del[x];
  31. add[x]=del[x]=pos[x]=tp[x]=0;
  32. }
  33. void build(int x)
  34. {
  35. memset(s[x],0,sizeof(s[x]));
  36. for(int i=(x-1)*b+1;i<=x*b;i++)
  37. {
  38. while(tp[x]>1&&(a[i]-a[top])*(top-dtp)>=(a[top]-a[dtp])*(i-top))--tp[x];
  39. s[x][++tp[x]]=i;
  40. }
  41. for(pos[x]=1;pos[x]<=tp[x]&&a[s[x][pos[x]+1]]>=a[s[x][pos[x]]];pos[x]++);
  42. }
  43. void update(int x)
  44. {
  45. for(;pos[x]<=tp[x];pos[x]++)
  46. if(a[s[x][pos[x]+1]]+add[x]*s[x][pos[x]+1]<a[s[x][pos[x]]]+add[x]*s[x][pos[x]])
  47. break;
  48. }
  49. int main()
  50. {
  51. n=gi(),m=gi();
  52. b=sqrt(n);
  53. for(int i=1;i<=n;i++) bel[i]=(i-1)/b+1,a[i]=gi();
  54. for(int i=1;i<=bel[n];i++) build(i);
  55. while(m--)
  56. {
  57. int op=gi(),l=gi(),r=gi();
  58. if(op==1)
  59. {
  60. ll k=a[1]+add[1]-del[1];
  61. ll mx=k;
  62. for(;bel[l]==bel[l-1]&&l<=r;l++)
  63. mx=max(mx,a[l]+add[bel[l]]*l-del[bel[l]]);
  64. for(;l+b<=r;l+=b)
  65. mx=max(mx,a[Max(bel[l])]+add[bel[l]]*Max(bel[l])-del[bel[l]]);
  66. for(;l<=r;l++)
  67. mx=max(mx,a[l]+add[bel[l]]*l-del[bel[l]]);
  68. printf("%lld\n",mx-k);
  69. }
  70. if(op==2)
  71. {
  72. remove(bel[l]),remove(bel[r]);
  73. swap(a[l],a[r]);
  74. build(bel[l]); build(bel[r]);
  75. }
  76. if(op==3)
  77. {
  78. int t=gi(),tl=l;
  79. for(;bel[l]==bel[l-1]&&l<=r;l++) a[l]+=(l-tl+1)*t;
  80. remove(bel[l-1]); build(bel[l-1]);
  81. for(;l+b<=r;l+=b) add[bel[l]]+=t,del[bel[l]]+=(tl-1)*t,update(bel[l]);
  82. for(;l<=r;l++) a[l]+=(l-tl+1)*t;
  83. remove(bel[r]); build(bel[r]);
  84. }
  85. }
  86. }

4. 附:维护上凸壳的正确性数学证明

附赠给不能理解维护上凸壳正确性的同学:

假设现在有3个元素 \(x,y,z\) ,设它们的编号分别为 \(h_x, h_y, h_z\),元素大小为 \(a_x,a_y,a_z\) ,权值为\(w_x,w_y,w_z\) , \(h_x<h_y<h_z\) 。设 \(add\) 值为 \(T\), 若存在 \(T\) 使得 \(w_y > w_x\) 且 \(w_y>w_z\),则作差列出不等式:

\(a_x-a_y<(h_y-h_x)T\) , \(a_y-a_z>(h_z-h_y)T\) .

两式整理合并可得 \(\displaystyle \frac{a_z-a_y}{h_z-h_y}<\frac{a_y-a_x}{h_y-h_x}\) .

即:直线 \(y\to z\) 的斜率小于直线 \(x\to y\) 的斜率,故维护上凸壳。同时易发现,随着 \(T\) 的不断增大,最大元素的位置右移,且最大元素左边的权值递增,右边的权值递减(即单峰)。

【Luogu2496】【BZOJ3005】[SDOI2012]体育课的更多相关文章

  1. P2496 [SDOI2012]体育课

    传送门 分块 对每个块维护一个 $add$ 和 $del$ 标记,对于块 $o$ 内某个位置 $i$,它真实的修改量为 $a[i]+add[o]*i-del[o]$ 这样就可以维护一个区间加一个等差数 ...

  2. BZOJ 2705: [SDOI2012]Longge的问题 [欧拉函数]

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2553  Solved: 1565[Submit][ ...

  3. BZOJ 2705: [SDOI2012]Longge的问题

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2554  Solved: 1566[Submit][ ...

  4. 【BZOJ】【2705】【SDOI2012】Longge的问题

    欧拉函数/狄利克雷卷积/积性函数 2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1275  Solv ...

  5. BZOJ 2705: [SDOI2012]Longge的问题 GCD

    2705: [SDOI2012]Longge的问题 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnl ...

  6. bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link

    2706: [SDOI2012]棋盘覆盖 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 255  Solved: 77[Submit][Status] ...

  7. bzoj 2705: [SDOI2012]Longge的问题 歐拉函數

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1035  Solved: 669[Submit][S ...

  8. Bzoj 2705: [SDOI2012]Longge的问题 欧拉函数,数论

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1959  Solved: 1229[Submit][ ...

  9. BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )

    考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N)  F, T均为后缀和. 与j有关 ...

随机推荐

  1. 几个原生js知识

    1.document.documentElement 返回根节点 html. 2.原生方法获取一个对象的某个样式的值. function getStyle(obj, attr) { if(obj.cu ...

  2. Git基本指令

    Git学习笔记 git //检查git是否安装 sudo apt-get install git git config --global user.name "dzq" git c ...

  3. Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig

    Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig at ...

  4. Mockito 中文文档 ( 2.0.26 beta )

    Mockito 中文文档 ( 2.0.26 beta ) 由于缺乏校对,难免有谬误之处,如果发现任何语句不通顺.翻译错误,都可以在github中的项目提出issue.谢谢~ Mockito框架官方地址 ...

  5. kubernetes从入门到放弃(二)

    kubernetes对象之pod 1.pod的认识 Pod直译是豆荚,可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起就是豆荚(一个Pod).在Kubernetes中我们不会直接操作容 ...

  6. Struts笔记一

    Struts 概念: 是一个MVC框架: Servlet的缺点 1.在web.xml中文件中需要配置很多行代码,维护起来很不方便呢,不利于团队合作. 2.一个servlet的入口只有一个doPost或 ...

  7. 为spring boot 写的Controller中的rest接口配置swagger

    1.pom.xml文件中加入下列依赖: <dependency> <groupId>io.springfox</groupId> <artifactId> ...

  8. 让eclipse恢复默认布局

    参考:https://blog.csdn.net/howlaa/article/details/39178359 Window -> Perspective -> Reset Perspe ...

  9. 夯实Java基础(二十一)——Java反射机制

    1.反射机制概述 Java反射机制是指程序在运行状态中,对于任何一个类,我们都能够知道这个类的所有属性和方法(包括private.protected等).对于任何一个对象,我们都能够对它的属性和方法进 ...

  10. python爬虫(九) requests库之post请求

    1.方法: response=requests.post("https://www.baidu.com/s",data=data) 2.拉勾网职位信息获取 因为拉勾网设置了反爬虫机 ...