不难发现,问题即求满足以下条件的$(i,j)$对数:

1.$1\le i<j\le n$且$a_{i}=a_{j}$

2.$\min_{i\le k\le j}y_{k}\ge l$且$\max_{i\le k\le j}y_{k}\le r$

先考虑条件1,枚举$1\le x\le n$,并对满足$a_{i}=x$的$i$个数$cnt$分类讨论:

1.若$cnt\le B$(其中$B$为常数),那么$a_{i}=a_{j}=x$的区间个数和(指对所有这样的$x$)不超过$nB$,暴力预处理出此类区间$y_{i}$的最小值和最大值,即变为一个二维数点的问题

关于这个二维数点,注意到点初始给定且条件只有一边,因此对其中一维使用扫描线处理,那么另外一维即变为支持单点修改和区间查询

由于有$o(nB)$次修改和$o(m)$次查询,为了均摊可以采取多层分块的结构,假设分$t$层,则修改和查询的复杂度分别为$o(nBt)$和$o(mn^{\frac{1}{t}}t)$(取$t=2$即为直接分块,取$t=\log_{2}n$即为线段树)

2.若$cnt>B$,那么这类$x$不超过$\frac{n}{B}$个,对应的$i$将序列划分若干段,并求出每一段$y_{i}$的最大值和最小值,注意到我们仅关心于$l,r$和这些最小值和最大值的关系,因此只有$o(cnt)$个本质不同的位置

由此使用莫队,问题即是要维护被包含的段长度(和和平方和),为了做到线性可以使用回滚莫队+链表,复杂度即$o(cnt\sqrt{m}+m)$,那么总复杂度为$o(n\sqrt{m}+\frac{nm}{B})$

另外,为了去掉其中的$\log$,具体实现是可能要借助基数排序等操作,可以参考代码

取$B=\sqrt{m}$和$t=3$即可,时间复杂度为$o(n\sqrt{m}+mn^{\frac{1}{3}})$,可以通过

(由于常数问题,取$B=4\sqrt{m}$更优,另外为了实现方便代码中取了$t=2$)

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 100005
  4. 4 #define M 1000005
  5. 5 #define ll long long
  6. 6 #define pii pair<int,int>
  7. 7 #define fi first
  8. 8 #define se second
  9. 9 struct Data{
  10. 10 int l,r,id;
  11. 11 bool operator < (const Data &k)const{
  12. 12 return ((l<k.l)||(l==k.l)&&(r<k.r));
  13. 13 }
  14. 14 }Q[M];
  15. 15 vector<int>v[N];
  16. 16 int n,m,B,x,P[N];
  17. 17 ll ans[M];
  18. 18 namespace ST{
  19. 19 int lg[N],mn[N][20],mx[N][20];
  20. 20 void init(){
  21. 21 lg[0]=-1;
  22. 22 for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
  23. 23 for(int i=1;i<=n;i++)mn[i][0]=mx[i][0]=P[i];
  24. 24 for(int i=n;i;i--)
  25. 25 for(int j=1;j<20;j++){
  26. 26 mn[i][j]=min(mn[i][j-1],mn[min(i+(1<<j-1),n)][j-1]);
  27. 27 mx[i][j]=max(mx[i][j-1],mx[min(i+(1<<j-1),n)][j-1]);
  28. 28 }
  29. 29 }
  30. 30 int get_min(int l,int r){
  31. 31 int m=lg[r-l+1];
  32. 32 return min(mn[l][m],mn[r-(1<<m)+1][m]);
  33. 33 }
  34. 34 int get_max(int l,int r){
  35. 35 int m=lg[r-l+1];
  36. 36 return max(mx[l][m],mx[r-(1<<m)+1][m]);
  37. 37 }
  38. 38 }
  39. 39 namespace Subtask1{
  40. 40 int f[N],sum[N];
  41. 41 vector<int>V[N];
  42. 42 void update(int k){
  43. 43 f[k]++,sum[k>>8]++;
  44. 44 }
  45. 45 int query(int k){
  46. 46 int ans=0;
  47. 47 for(int i=0;i<(k>>8);i++)ans+=sum[i];
  48. 48 for(int i=((k>>8)<<8);i<=k;i++)ans+=f[i];
  49. 49 return ans;
  50. 50 }
  51. 51 void calc(){
  52. 52 for(int i=1;i<=n;i++)
  53. 53 if (v[i].size()<=B){
  54. 54 for(int x=0;x<v[i].size();x++)
  55. 55 for(int y=x+1;y<v[i].size();y++){
  56. 56 int mn=ST::get_min(v[i][x],v[i][y]);
  57. 57 V[mn].push_back(ST::get_max(v[i][x],v[i][y]));
  58. 58 }
  59. 59 }
  60. 60 for(int i=n,k=m;i;i--){
  61. 61 for(int j=0;j<V[i].size();j++)update(V[i][j]);
  62. 62 while ((k)&&(Q[k].l==i)){
  63. 63 ans[Q[k].id]+=query(Q[k].r);
  64. 64 k--;
  65. 65 }
  66. 66 }
  67. 67 }
  68. 68 }
  69. 69 namespace Subtask2{
  70. 70 vector<int>V[N];
  71. 71 int sz,cnt,K,l,r,mn[N],mx[N],vis[N],id[N],pos[N],L0[N],L1[N],R0[N],R1[N],L[N],R[N],mnV[N];
  72. 72 ll Ans[N];
  73. 73 void init(){
  74. 74 Ans[0]=0;
  75. 75 memset(vis,0,sizeof(vis));
  76. 76 memset(L,0,sizeof(L));
  77. 77 memset(R,0,sizeof(R));
  78. 78 }
  79. 79 void check_add(int k){
  80. 80 if ((vis[k])&&(vis[k+1])){
  81. 81 Ans[0]+=(ll)(k-L[k]+1)*(R[k+1]-k);
  82. 82 R[L[k]]=R[k+1],L[R[k+1]]=L[k];
  83. 83 }
  84. 84 }
  85. 85 void check_del(int k){
  86. 86 if ((vis[k])&&(vis[k+1])){
  87. 87 R[L[k]]=k,L[R[k+1]]=k+1;
  88. 88 Ans[0]-=(ll)(k-L[k]+1)*(R[k+1]-k);
  89. 89 }
  90. 90 }
  91. 91 void add(int k){
  92. 92 vis[k]=1,L[k]=R[k]=k,Ans[0]++;
  93. 93 check_add(k-1),check_add(k);
  94. 94 }
  95. 95 void del(int k){
  96. 96 check_del(k-1),check_del(k);
  97. 97 vis[k]=L[k]=R[k]=0,Ans[0]--;
  98. 98 }
  99. 99 void addl(){
  100. 100 if ((L0[l])&&(mx[L0[l]]<=pos[r]))del(L0[l]);
  101. 101 if ((L1[l])&&(mx[L1[l]]<=pos[r]))del(L1[l]);
  102. 102 l++;
  103. 103 }
  104. 104 void decl(){
  105. 105 l--;
  106. 106 if ((L0[l])&&(mx[L0[l]]<=pos[r]))add(L0[l]);
  107. 107 if ((L1[l])&&(mx[L1[l]]<=pos[r]))add(L1[l]);
  108. 108 }
  109. 109 void addr(){
  110. 110 r++;
  111. 111 if ((R0[r])&&(pos[l]<=mn[R0[r]]))add(R0[r]);
  112. 112 if ((R1[r])&&(pos[l]<=mn[R1[r]]))add(R1[r]);
  113. 113 }
  114. 114 void decr(){
  115. 115 if ((R0[r])&&(pos[l]<=mn[R0[r]]))del(R0[r]);
  116. 116 if ((R1[r])&&(pos[l]<=mn[R1[r]]))del(R1[r]);
  117. 117 r--;
  118. 118 }
  119. 119 void calc(int k){
  120. 120 sz=v[k].size(),cnt=0;
  121. 121 memset(vis,0,sizeof(vis));
  122. 122 memset(L0,0,sizeof(L0));
  123. 123 memset(L1,0,sizeof(L1));
  124. 124 memset(R0,0,sizeof(R0));
  125. 125 memset(R1,0,sizeof(R1));
  126. 126 for(int i=1;i<sz;i++){
  127. 127 mn[i]=ST::get_min(v[k][i-1],v[k][i]);
  128. 128 mx[i]=ST::get_max(v[k][i-1],v[k][i]);
  129. 129 vis[mn[i]]=vis[mx[i]]=1;
  130. 130 }
  131. 131 for(int i=1;i<=n;i++){
  132. 132 if (vis[i])pos[++cnt]=i;
  133. 133 id[i]=cnt;
  134. 134 }
  135. 135 for(int i=1;i<sz;i++){
  136. 136 if (!L0[id[mn[i]]])L0[id[mn[i]]]=i;
  137. 137 else L1[id[mn[i]]]=i;
  138. 138 if (!R0[id[mx[i]]])R0[id[mx[i]]]=i;
  139. 139 else R1[id[mx[i]]]=i;
  140. 140 }
  141. 141 K=max(cnt/B,1);
  142. 142 for(int i=0,k=1;i*K<cnt;i++){
  143. 143 init();
  144. 144 int st=i*K+1,ed=min((i+1)*K,cnt);
  145. 145 for(int j=st;j<=cnt;j++){
  146. 146 mnV[j]=0x3f3f3f3f;
  147. 147 V[j].clear();
  148. 148 }
  149. 149 while ((k<=m)&&(Q[k].l<=pos[ed])){
  150. 150 mnV[id[Q[k].r]]=min(mnV[id[Q[k].r]],id[Q[k].l-1]+1);
  151. 151 V[id[Q[k].r]].push_back(k);
  152. 152 k++;
  153. 153 }
  154. 154 for(int j=st;j<ed;j++){
  155. 155 l=j+1,r=j,Ans[0]=Ans[j+1]=0;
  156. 156 while (mnV[j]<l){
  157. 157 decl();
  158. 158 Ans[l]=Ans[0];
  159. 159 }
  160. 160 for(int k=0;k<V[j].size();k++)ans[Q[V[j][k]].id]+=Ans[id[Q[V[j][k]].l-1]+1];
  161. 161 while (l<=j)addl();
  162. 162 }
  163. 163 l=ed,r=ed-1,Ans[0]=0;
  164. 164 for(int j=ed;j<=cnt;j++){
  165. 165 addr();
  166. 166 Ans[l]=Ans[0];
  167. 167 while (mnV[j]<l){
  168. 168 decl();
  169. 169 Ans[l]=Ans[0];
  170. 170 }
  171. 171 for(int k=0;k<V[j].size();k++)ans[Q[V[j][k]].id]+=Ans[id[Q[V[j][k]].l-1]+1];
  172. 172 while (l<ed)addl();
  173. 173 Ans[0]=Ans[l];
  174. 174 }
  175. 175 }
  176. 176 }
  177. 177 void calc(){
  178. 178 for(int i=1;i<=n;i++)
  179. 179 if (v[i].size()>B)calc(i);
  180. 180 }
  181. 181 }
  182. 182 int main(){
  183. 183 ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
  184. 184 cin>>n>>m;
  185. 185 B=4*(int)sqrt(m);
  186. 186 for(int i=1;i<=n;i++){
  187. 187 cin>>x;
  188. 188 v[x].push_back(i);
  189. 189 }
  190. 190 for(int i=1;i<=n;i++)cin>>P[i];
  191. 191 for(int i=1;i<=m;i++){
  192. 192 cin>>Q[i].l>>Q[i].r;
  193. 193 Q[i].id=i;
  194. 194 }
  195. 195 sort(Q+1,Q+m+1);
  196. 196 ST::init();
  197. 197 Subtask1::calc();
  198. 198 Subtask2::calc();
  199. 199 for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
  200. 200 return 0;
  201. 201 }

[hdu7099]Just Another Data Structure Problem的更多相关文章

  1. CDOJ 483 Data Structure Problem DFS

    Data Structure Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/proble ...

  2. ZOJ 4009 And Another Data Structure Problem(ZOJ Monthly, March 2018 Problem F,发现循环节 + 线段树 + 永久标记)

    题目链接  ZOJ Monthly, March 2018 Problem F 题意很明确 这个模数很奇妙,在$[0, mod)$的所有数满足任意一个数立方$48$次对$mod$取模之后会回到本身. ...

  3. HDU 6649 Data Structure Problem(凸包+平衡树)

    首先可以证明,点积最值的点对都是都是在凸包上,套用题解的证明:假设里两个点都不在凸包上, 考虑把一个点换成凸包上的点(不动的那个点), 不管你是要点积最大还是最小, 你都可以把那个不动的点跟原点拉一条 ...

  4. [hdu7097]Just a Data Structure Problem

    (四边形不等式的套路题) 对于某一组$a_{i}$,显然可以区间dp,设$f_{l,r}$表示区间$[l,r]$​的答案,则转移即$$f_{l,r}=\begin{cases}0&(l=r)\ ...

  5. [LeetCode] Add and Search Word - Data structure design 添加和查找单词-数据结构设计

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

  6. hdu-5929 Basic Data Structure(双端队列+模拟)

    题目链接: Basic Data Structure Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Ja ...

  7. HDU 5929 Basic Data Structure 模拟

    Basic Data Structure Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  8. hdu 4217 Data Structure? 树状数组求第K小

    Data Structure? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. (*medium)LeetCode 211.Add and Search Word - Data structure design

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

随机推荐

  1. Schematics Tools(Schematics 工具)

    Schematics工具 # Process: 创建逻辑示意图 arcpy.CreateDiagram_schematics("", "", "&qu ...

  2. vue基础-动态样式&表单绑定&vue响应式原理

    动态样式 作用:使用声明式变量来控制class和style的值 语法: :class/:style 注意:尽可能不要把动态class和静态class一起使用,原因动态class起作用的时间会比较晚,需 ...

  3. Spark解决SQL和RDDjoin结果不一致问题(工作实录)

    问题描述:DataFrame的join结果不正确,dataframeA(6000无重复条数据) join dataframeB(220条无重复数据,由dataframeA转化而来,key值均源于dat ...

  4. programmercarl——数组——二分查找

    二分查找,在经过: 34--https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-arr ...

  5. 【c++ Prime 学习笔记】第19章 特殊工具与技术

    某些程序对内存分配有特殊要求,不能直接使用标准内存管理机制 重载new和delete算符可控制内存分配的过程 19.1.1 重载new和delete 说法"重载new和delete" ...

  6. UI自动化测试之Airtest

    官方文档: https://airtest.doc.io.netease.com/ 本文我们讲解下Airtest的使用,主要学习目标有以下几点: (1)认识Airtest (2)了解Airtest能做 ...

  7. JVM:参数调优

    JVM:参数调优 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 前言 查看 JVM 系统默认值:使用 jps 和 jinfo 进行查看 -Xms:初始堆空间 - ...

  8. spring源码分析(二)- 容器基础

    1.基本用法 用过Spring的都知道,bean是Spring中最基础也是最核心的.首先看一个简单的例子. 一个类和一个配置文件 package bean; public class MyBean { ...

  9. centOs7.6安装 mysql-8.0.27

    1.下载mysql 2.连接服务器 3.通过 rpm -qa | grep mariadb 命令查看 mariadb 的安装包 4.通过 rpm -e mariadb-libs-5.5.68-1.el ...

  10. Python触发异常

    我们可以使用raise语句自己触发异常,raise语法格式如下: raise [Exception [, args [, traceback]]] 语句中 Exception 是异常的类型(例如,Na ...