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

思路:
  分治。
  对于一个区间$[l,r]$,设$mid=\lfloor\frac{l+r}{2}\rfloor$,我们可以求出所有经过$mid$的区间内能够成为众数的所有数。
  不难发现所有的区间众数满足如下一个性质:如果$x$是区间$[l,r]$的众数,那么对于$l\leq x\leq r$,$x$一定是区间$[l,k]$或区间$(k,r]$的众数。
  利用这一性质,我们可以令$k=mid$,这样就可以$O(n)$从$mid$出发往左右两边扫,求出能够成为众数的所有数。
  接下来枚举每个众数$x$,求一下当前$[l,r]$区间中,以$x$作为众数的子区间个数。
  具体我们可以先从$mid$往左扫,设往左扫到的端点为$b$,记录一下对于不同的$b$,$mid-b+1-cnt[x]$不同取值的出现次数。然后再往右扫,求出对于当前右端点$e$,求出满足$e-b+1-cnt[x]>\lfloor\frac{e-b+1}{2}\rfloor$的区间$[b,e]$的个数,这可以用前缀和快速求出。
  这样我们就统计了区间$[l,r]$,经过$mid$的所有子区间。
  对于不经过$mid$的子区间可以递归求解。
  递归树中,每一层区间长度加起来是$n$,可能的众数个数有$\log n$个,每一层的时间复杂度是$O(n\log n)$。总共有$\log n$层,总的时间复杂度是$O(n\log^2 n)$。

 #include<cstdio>
#include<cctype>
#include<algorithm>
typedef long long int64;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=;
int a[N],pos[N],num[N],cnt[N*];
int64 ans;
void solve(const int &l,const int &r) {
if(l==r) {
ans++;
return;
}
const int mid=(l+r)/;
solve(l,mid);
solve(mid+,r);
for(register int i=mid;i>=l;i--) {
if(++cnt[a[i]]>(mid-i+)/) {
if(!pos[a[i]]) {
num[pos[a[i]]=++num[]]=a[i];
}
}
}
for(register int i=mid+;i<=r;i++) {
if(++cnt[a[i]]>(i-mid)/) {
if(!pos[a[i]]) {
num[pos[a[i]]=++num[]]=a[i];
}
}
}
for(register int i=l;i<=r;i++) {
pos[a[i]]=cnt[a[i]]=;
}
for(register int i=;i<=num[];i++) {
int sum=r-l+,max=sum,min=sum;
cnt[sum]=;
for(register int j=l;j<mid;j++) {
if(a[j]==num[i]) {
sum++;
} else {
sum--;
}
max=std::max(max,sum);
min=std::min(min,sum);
cnt[sum]++;
}
if(a[mid]==num[i]) {
sum++;
} else {
sum--;
}
for(register int i=min;i<=max;i++) {
cnt[i]+=cnt[i-];
}
for(register int j=mid+;j<=r;j++) {
if(a[j]==num[i]) {
sum++;
} else {
sum--;
}
ans+=cnt[std::min(max,sum-)];
}
for(register int i=min;i<=max;i++) {
cnt[i]=;
}
}
num[]=;
}
int main() {
const int n=getint(); getint();
for(register int i=;i<=n;i++) {
a[i]=getint();
}
solve(,n);
printf("%lld\n",ans);
return ;
}

[BZOJ5110]Yazid的新生舞会的更多相关文章

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

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

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

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

  3. 【bzoj5110】Yazid的新生舞会

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

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

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

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

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

  6. 【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap

    题目描述 求一个序列所有的子区间,满足区间众数的出现次数大于区间长度的一半. 输入 第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型.数据类型的作用将在子任务中说明. 第二行n个用 ...

  7. BZOJ5110 CodePlus2017Yazid 的新生舞会(线段树)

    考虑统计每个数字的贡献.设f[i]为前缀i中该数的出现次数,则要统计f[r]-f[l]>(r-l)/2的数对个数,也即2f[r]-r>2f[l]-l. 注意到所有数的f的总变化次数是线性的 ...

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

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

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

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

随机推荐

  1. sentry

    https://docs.sentry.io/quickstart/?platform=javascript

  2. iis如何处理并发请求

    文章:IIS是怎么处理同时到来的多个请求的? 文章:你真的了解:IIS连接数.IIS并发连接数.IIS最大并发工作线程数.应用程序池的队列长度.应用程序池的... 文章:IIS最大工作进程数设置引发串 ...

  3. Java中常用的正则表达式判断,如IP地址、电话号码、邮箱等

    java中我们会常用一些判断如IP.电子邮箱.电话号码的是不是符合,那么我们怎么来判断呢,答案就是利用正则表达式来判断了,因为本人对正则表达式没有太深的研究,所有感兴趣的朋友可以自行百度.我这就给基本 ...

  4. Thymeleaf 模板 在spring boot 中的引用和应用

    Thymeleaf是一个java类库,他是一个xml/xhtml/html5的模板引擎和Struts框架的freemarker模板类似,可以作为mvc的web应用的view层. Thymeleaf还提 ...

  5. BZOJ 1036 [ZJOI2008]树的统计Count | 树链剖分模板

    原题链接 树链剖分的模板题:在点带权树树上维护路径和,最大值和单点修改 这里给出几个定义 以任意点为根,然后记 size (u ) 为以 u 为根的子树的结点个数,令 v 为 u 所有儿子中 size ...

  6. BZOJ1821 [JSOI2010]Group 部落划分 Group 【最小生成树】

    题目 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落之间则经常发生争斗.只是,这一切都成为谜团了--聪聪根 ...

  7. Eclipse 日文乱码怎么解决Shift_JIS

    https://jingyan.baidu.com/article/870c6fc325a691b03fe4beac.html Eclipse设置编码的地方主要有三处,这三处的设置都会影响中文的显示. ...

  8. Codeforces Round #356 (Div. 2) C

    C. Bear and Prime 100 time limit per test 1 second memory limit per test 256 megabytes input standar ...

  9. 怎么用SecureCRT这个工具把linux服务器的压缩文件下载到本地的一个路径。

    依次按上图中所示的突变,进入sftp的命令界面.输入help命令:即:sftp>help得到如下的截图. 比较重要的命令有:cd----查询服务器端的路径 lcd---查询本地的地址 pwd:服 ...

  10. RabbitMQ Windows下安装问题解决

    一.问题描述 安装后出现如下问题描述 C:\Program Files\RabbitMQ Server\rabbitmq_server-3.4.3\sbin>rabbitmqctl status ...