题目描述

求一个序列所有的子区间,满足区间众数的出现次数大于区间长度的一半。

输入

第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型。数据类型的作用将在子任务中说明。
第二行n个用空格隔开的非负整数,依次为A1,A2,...,An,描述这个序列。
N<=500000,0<=Type<=3
对于所有数据,保证 0 ≤ Ai ≤ n - 1。
对于 type = 0 的数据,没有任何特殊约定。
对于 type = 1 的数据,保证 Ai ∈ {0, 1}。
对于 type = 2 的数据,保证序列 A 的众数在整个序列中的出现次数不超过 15。
对于 type = 3 的数据,保证 Ai ≤ 7。

输出

输出一行一个整数,表示答案。

样例输入

5 0
1 1 2 2 3

样例输出

10


题解

Treap

做麻烦了...

先把所有相同的数出现的位置存到一个vector里,然后考虑这个数作为众数的贡献。

考虑枚举贡献段的最后一个数的位置,这样对于某个左边的该数出现的位置,区间长度应该满足:区间长度小于2*这段中该数的个数。

如果设 x 表示右端点位置, y 表示右端点在某位置下满足条件的区间个数。那么由于区间长度一定,可以得到一个 y=-x+b 类型的直线(实际上有意义的只有第一象限的部分)。

但是这样会有一个问题:某些区间会计算重复。

由于考虑的是这段该数出现位置的贡献,因此区间不能包含其它的该数,即贡献区间的最端点不能达到上一个出现位置。

因此可以得到如下的图:

(好,以上只是理论部分...)

考虑一下我们需要做的:

我们枚举该数出现位置的右端点,并计算 [上一个出现的位置,当前位置) 区间的贡献。我们维护所有前面的这样的折线,统计所有折线在这段区间的面积和。

然后,由于多了当前位置,相当于以前的区间中选择区间的长度加了2,因此这些折线需要向右平移2个单位。

最后,需要把当前位置对应的折线维护起来。

一条折线可以看作是两条直线作差,因此我们需要做的有:添加直线、维护直线面积、支持直线集体向右平移。可以使用Treap来维护。

按照直线与x轴交点来维护,维护直线的斜率、截距、面积,以及子树中这三者的和。插入直接正常插入,整体平移则直接打标记。

统计面积的过程可以转化为前缀相减。在Treap上查询,如果其与左边的位置都小于当前位置,那么左边的答案就是面积总和,递归右子树;否则右边的贡献都是梯形面积(转化为等差数列求和),递归左子树。

然后就可以了,注意开long long。

细节贼多...

时间复杂度$O(n\log n)$

然后我考试时写的SBT,由于没有在旋转时pushdown(震惊!SBT竟然要在旋转时pushdown)导致爆0,再也不写SBT了...

附上Treap的代码:

  1. #include <vector>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #define N 500010
  6. using namespace std;
  7. typedef long long ll;
  8. vector<int> v[N];
  9. int l[N] , r[N] , rnd[N] , tot , root , a[N];
  10. ll vp[N] , tag[N] , wk[N] , wb[N] , ws[N] , sk[N] , sb[N] , ss[N];
  11. inline void add(int k , ll x)
  12. {
  13. vp[k] += x;
  14. ws[k] += (2 * wb[k] - (x + 1) * wk[k]) * x / 2;
  15. ss[k] += (2 * sb[k] - (x + 1) * sk[k]) * x / 2;
  16. wb[k] -= wk[k] * x;
  17. sb[k] -= sk[k] * x;
  18. tag[k] += x;
  19. }
  20. inline void pushup(int k)
  21. {
  22. sk[k] = sk[l[k]] + sk[r[k]] + wk[k];
  23. sb[k] = sb[l[k]] + sb[r[k]] + wb[k];
  24. ss[k] = ss[l[k]] + ss[r[k]] + ws[k];
  25. }
  26. inline void pushdown(int k)
  27. {
  28. if(tag[k]) add(l[k] , tag[k]) , add(r[k] , tag[k]) , tag[k] = 0;
  29. }
  30. inline void zig(int &k)
  31. {
  32. int t = l[k];
  33. l[k] = r[t] , r[t] = k , pushup(k) , pushup(t) , k = t;
  34. }
  35. inline void zag(int &k)
  36. {
  37. int t = r[k];
  38. r[k] = l[t] , l[t] = k , pushup(k) , pushup(t) , k = t;
  39. }
  40. void insert(int &k , ll p , ll xk , ll xb)
  41. {
  42. if(!k)
  43. {
  44. k = ++tot , vp[k] = p , wk[k] = sk[k] = xk , wb[k] = sb[k] = xb , ws[k] = ss[k] = xb * (p + 1) / 2 , rnd[k] = rand();
  45. return;
  46. }
  47. pushdown(k);
  48. if(p < vp[k])
  49. {
  50. insert(l[k] , p , xk , xb) , pushup(k);
  51. if(rnd[l[k]] < rnd[k]) zig(k);
  52. }
  53. else
  54. {
  55. insert(r[k] , p , xk , xb) , pushup(k);
  56. if(rnd[r[k]] < rnd[k]) zag(k);
  57. }
  58. }
  59. ll query(int k , ll p)
  60. {
  61. if(!k) return 0;
  62. pushdown(k);
  63. if(p < vp[k]) return (2 * (wb[k] + sb[r[k]]) + (wk[k] + sk[r[k]]) * p) * (p + 1) / 2 + query(l[k] , p);
  64. else return ws[k] + ss[l[k]] + query(r[k] , p);
  65. }
  66. void clear(int k)
  67. {
  68. if(!k) return;
  69. clear(l[k]) , clear(r[k]) , l[k] = r[k] = vp[k] = tag[k] = wk[k] = wb[k] = ws[k] = sk[k] = sb[k] = ss[k] = 0;
  70. }
  71. int main()
  72. {
  73. int n , i , pos;
  74. ll ans = 0;
  75. unsigned j;
  76. scanf("%d%*d" , &n);
  77. for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , v[++a[i]].push_back(i);
  78. for(i = 1 ; i <= n ; i ++ ) v[i].push_back(n + 1);
  79. for(i = 1 ; i <= n ; i ++ )
  80. {
  81. pos = 0;
  82. for(j = 0 ; j < v[i].size() ; j ++ )
  83. {
  84. ans += query(root , v[i][j] - 1) - query(root , pos - 1);
  85. add(root , 2);
  86. insert(root , v[i][j] + 1 , -1 , v[i][j] + 1) , insert(root , pos + 1 , 1 , -pos - 1);
  87. pos = v[i][j];
  88. }
  89. clear(root) , root = tot = 0;
  90. }
  91. printf("%lld\n" , ans);
  92. return 0;
  93. }

【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap的更多相关文章

  1. bzoj5110: [CodePlus2017]Yazid 的新生舞会

    Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一个子区间[l,r] ,如果该子区间内的众数在该子区间的出现次数严格大于( ...

  2. 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会 线段树

    [BZOJ5110][CodePlus2017]Yazid 的新生舞会 Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一 ...

  3. 【bzoj5110】Yazid的新生舞会

    这里是 $THUWC$ 选拔时间 模拟赛的时候犯 $SB$ 了,写了所有的部分分,然后直接跑过了 $4$ 个大样例(一个大样例是一个特殊情况)…… 我还以为我非常叼,部分分都写对了,于是就不管了…… ...

  4. 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会

    题解: 没笔的时候我想了一下 发现如果不是出现一半次数而是k次,并不太会做 然后我用前缀和写了一下发现就是维护一个不等式: 于是就可以随便维护了

  5. BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)

    LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...

  6. [loj 6253] Yazid的新生舞会

    (很久之前刷的题现在看起来十分陌生a) 题意: 给你一个长度为n的序列A,定义一个区间$[l,r]$是“新生舞会的”当且仅当该区间的众数次数严格大于$\frac{r-l+1}{2}$,求有多少子区间是 ...

  7. [BZOJ5110]Yazid的新生舞会

    题目大意: 给你一个长度为$n(n\leq 5\times 10^5)$的序列$A_{1\sim n}$.求满足区间众数在区间内出现次数严格大于$\lfloor\frac{r-l+1}{2}\rflo ...

  8. 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)

    学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2 ...

  9. bzoj 5110 Yazid的新生舞会

    题目大意: 一个数列,求有多少个区间$[l,r]$满足该区间的众数出现次数大于$\lceil \frac{r-l}{2} \rceil$ 思路: 对于一个区间满足条件的众数明显是唯一的 所以设该数的前 ...

随机推荐

  1. [原创]记一次java执行段错误及解决过程

    最近一周左右,网管监控系统经常监控到tomcat异常退出,由于有检测tomcat pid的脚本,所以会自动重启服务器,查询tomcat日志没有报错信息,查询系统message日志,可以看到如下信息. ...

  2. python3 使用语音库pyttsx3

    python3 使用语音库pyttsx3 环境linux+python3.6 sudo pip install pyttsx3 sudo apt-get install espeak 代码实例 imp ...

  3. 不搭建git服务器对git仓库进行局域网内共享多人合作开发项目

    有时候在一个临时局域网内没有搭建git服务器,但是又想多人开发一个项目,此时只要每个人电脑安装有git客户端,参考一下方法即可尝试建一个本地化的远程仓库进行多人开发工作. 远程仓库通常只是一个裸仓库( ...

  4. 北京Uber优步司机奖励政策(12月8日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  5. define的误用

    #define LIGHT_SPEED 3e8 // m/sec (in a vacuum)

  6. eclipse报这个错误org.eclipse.swt.SWTError: No more handles (eclipse 和 TeamViewer 冲突)

    错误:  org.eclipse.swt.SWTError: No more handles     at org.eclipse.swt.SWT.error(SWT.java:4387)     a ...

  7. redux devtools调试工具

    项目安装: npm install redux-devtools-extension -dev 谷歌搜索 Redux DevTools 安装: 使用: 主要用到state&Dispatcher ...

  8. hdu1907John(反nim博弈)

    John Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  9. appium -- 页面出现弹窗,关闭后,无法识别页面元素

    1. 问题:如图所示:在修改手势密码的过程中,点击了返回按钮后,弹出该弹窗:点击继续设置后,就发现 driver.getPageSource()获取不到页面元素.在找了一圈无用的资料后,没有什么好的处 ...

  10. Jenkis 无法下载插件问题解决

    在新机器上安装jenkins后,安装插件报如下错误 sun.security.provider.certpath.SunCertPathBuilderException: unable to find ...