称区间$[l,r]$的"信息"为其的答案和第一个、最后一个大于$x$的位置,显然通过$[l,mid]$和$[mid+1,r]$的信息可以$o(1)$合并得到$[l,r]$的信息

考虑分块,将其按$K$的块大小分块,区间查询时求出散块每一个位置的信息(将其看作一个区间)和每一个整块的信息,之后即可$o(K+\frac{n}{K})$合并得到整个块的信息

下面的问题即如何求整块的信息,对整块维护:1.排序后的结果;2.当$x$为块中每一个元素时的信息;3.[luogu6466]分散层叠算法的做法4所维护的分治结构(将$x$作为小于等于$x$的最大元素即可)

对于排序后的结果时间复杂度为$o(n\log n)-o(K)$(单点修改即插入排序),当得到排序后的结果后,该块的"信息"也可以在$o(K)$的复杂度内得到——

关于答案,只需要从小到大枚举元素,每一次即加入一个元素,通过链表支持合并即可

关于第一个和最后一个大于$x$的位置,维护排序后的序列位置的后缀最小值和最大值即可

由此即可支持单点修改,单次复杂度为$o(K)$,取$K=\sqrt{n}$单次复杂度即$o(\sqrt{n})$

时间复杂度为$o(n\log n)-o(\sqrt{n})$

(由于该oj似乎不支持提交,与某个通过的代码拍过,正确性大概是能保证的,速度大约是其1.5倍)

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 300005
  4. 4 #define K 600
  5. 5 #define D 3
  6. 6 #define ll long long
  7. 7 #define L (k<<1)
  8. 8 #define R (L+1)
  9. 9 #define mid (l+r>>1)
  10. 10 struct Data{
  11. 11 int l,r;
  12. 12 ll ans;
  13. 13 }ans[N];
  14. 14 int n,m,k,p,x,y,z,num[21],a[N],bl[N],st[K],ed[K],id[N];
  15. 15 int read(){
  16. 16 int x=0;
  17. 17 char c=getchar();
  18. 18 while ((c<'0')||(c>'9'))c=getchar();
  19. 19 while ((c>='0')&&(c<='9')){
  20. 20 x=x*10+(c-'0');
  21. 21 c=getchar();
  22. 22 }
  23. 23 return x;
  24. 24 }
  25. 25 void write(ll x,char c='\0'){
  26. 26 while (x){
  27. 27 num[++num[0]]=x%10;
  28. 28 x/=10;
  29. 29 }
  30. 30 if (!num[0])putchar('0');
  31. 31 while (num[0])putchar(num[num[0]--]+'0');
  32. 32 putchar(c);
  33. 33 }
  34. 34 bool cmp(int x,int y){
  35. 35 return a[x]<a[y];
  36. 36 }
  37. 37 bool Cmp(int x,int y){
  38. 38 return a[x]<=y;
  39. 39 }
  40. 40 Data merge(Data x,Data y);
  41. 41 namespace Rope{
  42. 42 int n,vis[N],l[N],r[N];
  43. 43 ll ans;
  44. 44 void init(int nn){
  45. 45 n=nn;
  46. 46 for(int i=0;i<=n+1;i++)vis[i]=0;
  47. 47 for(int i=1;i<=n;i++)l[i]=r[i]=i;
  48. 48 }
  49. 49 void link(int x){
  50. 50 ans+=(ll)(x-l[x]+1)*(r[x+1]-x);
  51. 51 l[r[x+1]]=l[x],r[l[x]]=r[x+1];
  52. 52 }
  53. 53 ll add(int x){
  54. 54 ans=vis[x]=1;
  55. 55 if (vis[x-1])link(x-1);
  56. 56 if (vis[x+1])link(x);
  57. 57 return ans;
  58. 58 }
  59. 59 };
  60. 60 namespace Seg{
  61. 61 int Pos[2],b[K<<2][K],pos[K<<2][K][2];
  62. 62 void get(int k,int x){
  63. 63 b[k][0]=0;
  64. 64 for(int i=st[x];i<=ed[x];i++)b[k][++b[k][0]]=id[i];
  65. 65 }
  66. 66 void up(int k){
  67. 67 b[k][0]=0;
  68. 68 int x=1,y=1;
  69. 69 while ((x<=b[L][0])||(y<=b[R][0])){
  70. 70 if ((x<=b[L][0])&&((y>b[R][0])||(cmp(b[L][x],b[R][y])))){
  71. 71 b[k][++b[k][0]]=b[L][x];
  72. 72 pos[k][b[k][0]][0]=x;
  73. 73 pos[k][b[k][0]][1]=0;
  74. 74 x+=D;
  75. 75 }
  76. 76 else{
  77. 77 b[k][++b[k][0]]=b[R][y];
  78. 78 pos[k][b[k][0]][0]=0;
  79. 79 pos[k][b[k][0]][1]=y;
  80. 80 y+=D;
  81. 81 }
  82. 82 }
  83. 83 memset(Pos,0,sizeof(Pos));
  84. 84 for(int i=1;i<=b[k][0];i++)
  85. 85 for(int p=0;p<2;p++){
  86. 86 if (pos[k][i][p])Pos[p]=pos[k][i][p];
  87. 87 pos[k][i][p]=Pos[p];
  88. 88 }
  89. 89 }
  90. 90 void build(int k,int l,int r){
  91. 91 if (l==r){
  92. 92 get(k,l);
  93. 93 return;
  94. 94 }
  95. 95 build(L,l,mid);
  96. 96 build(R,mid+1,r);
  97. 97 up(k);
  98. 98 }
  99. 99 void update_point(int k,int l,int r,int x){
  100. 100 if (l==r){
  101. 101 get(k,x);
  102. 102 return;
  103. 103 }
  104. 104 if (x<=mid)update_point(L,l,mid,x);
  105. 105 else update_point(R,mid+1,r,x);
  106. 106 up(k);
  107. 107 }
  108. 108 void query_seg(int k,int l,int r,int x,int y,int z,int w){
  109. 109 if ((l>y)||(x>r))return;
  110. 110 if (!z){
  111. 111 ans[0]=merge(ans[0],Data{0,0,0});
  112. 112 return;
  113. 113 }
  114. 114 if (l==r){
  115. 115 ans[0]=merge(ans[0],ans[b[k][z]]);
  116. 116 return;
  117. 117 }
  118. 118 int zl=pos[k][z][0],zr=pos[k][z][1];
  119. 119 while ((zl<b[L][0])&&(Cmp(b[L][zl+1],w)))zl++;
  120. 120 while ((zr<b[R][0])&&(Cmp(b[R][zr+1],w)))zr++;
  121. 121 query_seg(L,l,mid,x,y,zl,w);
  122. 122 query_seg(R,mid+1,r,x,y,zr,w);
  123. 123 }
  124. 124 void query(int l,int r,int x){
  125. 125 if (l>r)return;
  126. 126 query_seg(1,1,bl[n],l,r,lower_bound(b[1]+1,b[1]+b[1][0]+1,x,Cmp)-b[1]-1,x);
  127. 127 }
  128. 128 };
  129. 129 Data merge(Data x,Data y){
  130. 130 Data ans;
  131. 131 ans.ans=x.ans+y.ans;
  132. 132 if ((x.r<0)&&(y.r<0)){
  133. 133 ans.l=x.l+y.l,ans.r=-1;
  134. 134 ans.ans+=(ll)x.l*y.l;
  135. 135 return ans;
  136. 136 }
  137. 137 if (x.r<0){
  138. 138 ans.l=x.l+y.l,ans.r=y.r;
  139. 139 ans.ans+=(ll)x.l*y.l;
  140. 140 return ans;
  141. 141 }
  142. 142 if (y.r<0){
  143. 143 ans.l=x.l,ans.r=x.r+y.l;
  144. 144 ans.ans+=(ll)x.r*y.l;
  145. 145 return ans;
  146. 146 }
  147. 147 ans.l=x.l,ans.r=y.r;
  148. 148 ans.ans+=(ll)x.r*y.l;
  149. 149 return ans;
  150. 150 }
  151. 151 void upd(int k,int x){
  152. 152 for(int i=st[k];i<=ed[k];i++)
  153. 153 if (id[i]==x){
  154. 154 x=i;
  155. 155 break;
  156. 156 }
  157. 157 int s=id[x];
  158. 158 for(int i=x;i<ed[k];i++)id[i]=id[i+1];
  159. 159 for(int i=st[k];i<ed[k];i++)
  160. 160 if (cmp(s,id[i])){
  161. 161 for(int j=ed[k];j>i;j--)id[j]=id[j-1];
  162. 162 id[i]=s;
  163. 163 return;
  164. 164 }
  165. 165 id[ed[k]]=s;
  166. 166 }
  167. 167 void calc(int k){
  168. 168 ans[id[ed[k]]].l=ed[k]-st[k]+1,ans[id[ed[k]]].r=-1;
  169. 169 int l=id[ed[k]]-st[k],r=ed[k]-id[ed[k]];
  170. 170 for(int i=ed[k]-1;i>=st[k];i--){
  171. 171 ans[id[i]].l=l,ans[id[i]].r=r;
  172. 172 l=min(l,id[i]-st[k]),r=min(r,ed[k]-id[i]);
  173. 173 }
  174. 174 Rope::init(ed[k]-st[k]+1);
  175. 175 ll sum=0;
  176. 176 for(int i=st[k];i<=ed[k];i++){
  177. 177 sum+=Rope::add(id[i]-st[k]+1);
  178. 178 ans[id[i]].ans=sum;
  179. 179 }
  180. 180 }
  181. 181 int main(){
  182. 182 n=read(),m=read(),k=(int)sqrt(n);
  183. 183 for(int i=1;i<=n;i++)a[i]=read();
  184. 184 for(int i=1;i<=n;i++){
  185. 185 id[i]=i;
  186. 186 bl[i]=(i-1)/k+1;
  187. 187 if (!st[bl[i]])st[bl[i]]=i;
  188. 188 ed[bl[i]]=i;
  189. 189 }
  190. 190 for(int i=1;i<=bl[n];i++){
  191. 191 sort(id+st[i],id+ed[i]+1,cmp);
  192. 192 calc(i);
  193. 193 }
  194. 194 Seg::build(1,1,bl[n]);
  195. 195 for(int i=1;i<=m;i++){
  196. 196 p=read(),x=read(),y=read();
  197. 197 if (p==1){
  198. 198 a[x]=y;
  199. 199 upd(bl[x],x);
  200. 200 calc(bl[x]);
  201. 201 Seg::update_point(1,1,bl[n],bl[x]);
  202. 202 }
  203. 203 else{
  204. 204 z=read();
  205. 205 ans[0]=Data{0,-1,0};
  206. 206 if (bl[x]==bl[y]){
  207. 207 for(int j=x;j<=y;j++)
  208. 208 if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
  209. 209 else ans[0]=merge(ans[0],Data{1,-1,1});
  210. 210 }
  211. 211 else{
  212. 212 for(int j=x;j<=ed[bl[x]];j++)
  213. 213 if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
  214. 214 else ans[0]=merge(ans[0],Data{1,-1,1});
  215. 215 Seg::query(bl[x]+1,bl[y]-1,z);
  216. 216 for(int j=st[bl[y]];j<=y;j++)
  217. 217 if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
  218. 218 else ans[0]=merge(ans[0],Data{1,-1,1});
  219. 219 }
  220. 220 write(ans[0].ans,'\n');
  221. 221 }
  222. 222 }
  223. 223 return 0;
  224. 224 }

[Comet1173]最简单的题的更多相关文章

  1. 2019浙大校赛--A--Thanks, TuSimple!(简单模拟题)

    这题前三段都是一堆吹爆赞助商的屁话,正式题目在图片下边,一个简单模拟题. 题目大意: 有n个男生,m个女生在进行舞会,其中一部分男生祥和比自己矮的女生跳舞,一部分男生想和比自己高的女生跳舞,一部分女生 ...

  2. 简单数据结构题(from 钟子谦——IOI2018集训队自选题)

    简单数据结构题(from 钟子谦--IOI2018集训队自选题) 试题描述 给一棵 \(n\) 个点的树,点权开始为 \(0\) ,有 \(q\) 次操作,每次操作是选择一个点,把周围一圈点点权 \( ...

  3. java算法题每日一练01,java入门简单算法题小练

    1.给数组做反序 public class Ak01 { public static void main(String[] args) { int[] a = new int[]{22,48,41,2 ...

  4. 一个简单算法题引发的思考<DNA sorting>(about cin/template/new etc)

    首先是昨天在北京大学oj网上看到一个简单的算法题目,虽然简单,但是如何完成一段高效.简洁.让人容易看懂的代码对于我这个基础不好,刚刚进入计算机行业的小白来说还是有意义的.而且在写代码的过程中,会发现自 ...

  5. UVa 679 小球下落 简单模拟题,树

    题目大意:给你一个完全二叉树,并且给他们编号,编号规则为左子树为2*k,右子树为2*k+1,每一个节点 上都有一个开关,初始时开关都处于关闭状态,小球碰到节点就会改变该点的开关的状态.然后给你I个小球 ...

  6. 一些简单二分题,简单的hash,H(i),字符串题

    说在前面: 题是乱七八糟的. 几个二分的题. (但是我的做法不一定是二分,有些裸暴力. 1. Equations HDU - 1496 输入a,b,c,d问你这个方程有多少解.a*x1^2+b*x2^ ...

  7. POJ 1008 简单模拟题

    e.... 虽然这是一道灰常简单的模拟题.但是米做的时候没有读懂第二个日历的计时方法.然后捏.敲完之后华丽的WA了进一个点.坑点就在一年的最后一天你是该输出本年的.e ...但是我好想并没有..看di ...

  8. [POJ1082&POJ2348&POJ1067&POJ2505&POJ1960]简单博弈题总结

    鉴于时间紧张...虽然知道博弈是个大课题但是花一个上午时间已经极限了... 希望省选过后再回过头来好好总结一遍吧. 接下来为了看着顺眼一点...还是按照难度顺序吧   POJ1082 一道最简单的博弈 ...

  9. HDU 4772 Zhuge Liang&#39;s Password (简单模拟题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4772 题面: Zhuge Liang's Password Time Limit: 2000/1000 ...

随机推荐

  1. RabbitMQ的web页面介绍(三)

    一.Virtual Hosts 每一个 RabbitMQ 服务器都能创建虚拟的消息服务器,我们称之为虚拟主机 (virtual host) ,简称为vhost.每一个 vhost 本质上是一个独立的小 ...

  2. 41 位 Contributor 参与,1574 个 PR,不容错过的版本更新!

    6 月 25 日,在商业公司 SphereEx 正式成立一月之余的今天,我们很高兴的宣布 Apache ShardingSphere 迎来了 5.0.0-beta 版本的正式发布.经过半年多的优化和打 ...

  3. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

  4. 2021年1月-第02阶段-前端基础-HTML+CSS进阶-VS Code 软件

    软件安装 VSCode软件 能够安装 VS Code 能够熟练使用 VS Code 软件 能够安装 VS Code 最常用的插件 1. VS Code简介 1.1 VS Code 简介 Visual ...

  5. Java中的函数式编程(六)流Stream基础

    写在前面 如果说函数式接口和lambda表达式是Java中函数式编程的基石,那么stream就是在基石上的最富丽堂皇的大厦. 只有熟悉了stream,你才能说熟悉了Java 的函数式编程. 本文主要介 ...

  6. Egg.js学习与实战系列 · 文件上传配置

    在使用Egg.js搭建文件上传服务时,遇到了几个一般新手都会遇到的坑. 经查阅官方文档,Egg框架中默认使用egg-multipart插件进行文件上传,所以上传文件前需要做相关的配置. 上传文件提示: ...

  7. keras框架下的深度学习(二)二分类和多分类问题

    本文第一部分是对数据处理中one-hot编码的讲解,第二部分是对二分类模型的代码讲解,其模型的建立以及训练过程与上篇文章一样:在最后我们将训练好的模型保存下来,再用自己的数据放入保存下来的模型中进行分 ...

  8. Java:并发笔记-03

    Java:并发笔记-03 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 3. 共享模型之管程-2 本章内容-2 Monitor wait/notify 3.6 ...

  9. rabbitmq死信队列和延时队列的使用

    死信队列&死信交换器:DLX 全称(Dead-Letter-Exchange),称之为死信交换器,当消息变成一个死信之后,如果这个消息所在的队列存在x-dead-letter-exchange ...

  10. Noip模拟32(再度翻车) 2021.8.7

    T1 Smooth 很水的一道题...可是最傻    的是考场上居然没有想到用优先队列优化... 上来开题看到这个,最一开始想,这题能用模拟短除法,再一想太慢了,就想着优化 偏偏想到线性筛然后试别的素 ...