link

$solution:$

不知道为什么别人的代码能写的非常短,难道就是写差分的好处?

这种题肯定是算每个众数的贡献,考虑通过暴力众数求出个数。

现在考虑众数 $x$ ,则在序列 $a$ 中将等于 $x$ 的置为 $1$ ,否则置为 $-1$,令为序列 $A$ 。设 $S_i=\sum_{k=1}^i A_k$。

若 $[l,r]$ 是满足题意的区间,则 $S_r>S_{l-1}$ ,所以对于每个众数 $x$ ,求出满足 $i>j,S_i>S_j$ 的方案数,直接求二维偏序即可,时间复杂度 $O(n^2\log n)$ ,并不能通过本题。

但是,我们能发现一个性质,在每个 $A$ 中只会有很少的 $1$ ,与很多的 $-1$ 出现,因为 $1$ 只能在 $A$ 中出现 $n$ 次。对于连续 $-1$ 段来说不可能 $l,r$ 均在其中,并且它们的 $S$ 值是每次减一,所以考虑将它们合为一个,其 $S$ 的范围为 $[L,R]$ ,可以简单发现连续段个数与 $n$ 同阶。

考虑将 $-1$ 连续段中作为右端点对答案的贡献,设 $l,r$ 为连续段的左右端点,$L,R$ 为 $S$ 的范围,$C_i$ 为满足 $S_k=i,k\in [0,i)$ 的个数。

则容易推出$$Ans=\sum_{i=-n}^{L-1} C_i\times (R-L+1)+\sum_{i=L}^R C_i\times (R-i)\\=\sum_{i=-n}^{L-1} C_i\times (R-L+1)+\sum_{i=L}^R C_i-\sum_{i=L}^R C_i\times i$$

发现 $\sum_{i=-n}^{L-1} C_i\times (R-L+1)$ 这两个式子直接线段树区间加法维护即可,而 $\sum_{i=L}^R C_i\times i$ 直接线段树上维护等差数列即可。

现在考虑完右端点在 $-1$ 的情况,而右端点在 $1$ 时直接线段树查询 $[-n,S_{i}-1]$ 即可。

因为区间段与 $n$ 同阶,所以时间复杂度为 $O(n\log n)$ 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define int long long
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int MAXN=;
int n,a[MAXN];
vector<int> ve[MAXN];
struct Segment1{
int Ans[MAXN<<],Beg[MAXN<<],D[MAXN<<],qx[MAXN],qy[MAXN],qbe[MAXN],qd[MAXN],tot;
inline void clear(){
for(int i=;i<=tot;i++) Modify(,,*n,qx[i],qy[i],-qbe[i],-qd[i]);
tot=;
}
inline void pushdown(int k,int l,int r){
int mid=l+r>>;
if(!Beg[k]&&!D[k]) return;
Ans[k<<]+=Beg[k]*(mid-l+)+((((mid-l+)*(mid-l))/)*D[k]);
Ans[k<<|]+=Beg[k]*(r-mid)+((((r+mid-*l+)*(r-mid))/)*D[k]);
Beg[k<<]+=Beg[k],Beg[k<<|]+=Beg[k]+(mid+-l)*D[k];
D[k<<]+=D[k],D[k<<|]+=D[k];
Beg[k]=D[k]=;
return;
}
inline void Modify(int k,int l,int r,int x,int y,int be,int d){
if(x<=l&&r<=y){
Ans[k]+=((r-l+)*be)+(((((l+r)*(r-l+))/)-(x*(r-l+)))*d);
Beg[k]+=(be+(l-x)*d);
D[k]+=d;
return;
}
pushdown(k,l,r);
int mid=l+r>>;
if(x<=mid) Modify(k<<,l,mid,x,y,be,d);
if(mid<y) Modify(k<<|,mid+,r,x,y,be,d);
Ans[k]=Ans[k<<]+Ans[k<<|];
return;
}
inline int Query(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return Ans[k];
pushdown(k,l,r);
int mid=l+r>>,res=;
if(x<=mid) res+=Query(k<<,l,mid,x,y);
if(mid<y) res+=Query(k<<|,mid+,r,x,y);
Ans[k]=Ans[k<<]+Ans[k<<|];return res;
}
inline void add(int x,int y,int be,int d){
qx[++tot]=x+n;qy[tot]=y+n;qbe[tot]=be,qd[tot]=d;
Modify(,,*n,x+n,y+n,be,d);return;
}
inline int Q(int x,int y){
return Query(,,*n,x+n,y+n);
}
}segment1;
struct Segment2{
int Ans[MAXN<<],tag[MAXN<<];
int qx[MAXN],qy[MAXN],qw[MAXN],tot;
inline void clear(){
for(int i=;i<=tot;i++) Modify(,,*n,qx[i],qy[i],-qw[i]);
tot=;
}
inline void pushdown(int k,int l,int r){
if(!tag[k]) return;
int mid=l+r>>;
Ans[k<<]+=tag[k]*(mid-l+);Ans[k<<|]+=tag[k]*(r-mid);
tag[k<<]+=tag[k],tag[k<<|]+=tag[k];
tag[k]=;return;
}
inline void Modify(int k,int l,int r,int x,int y,int w){
if(x<=l&&r<=y){
tag[k]+=w;
Ans[k]+=(r-l+)*w;return;
}
pushdown(k,l,r);
int mid=l+r>>;
if(x<=mid) Modify(k<<,l,mid,x,y,w);
if(mid<y) Modify(k<<|,mid+,r,x,y,w);
Ans[k]=Ans[k<<]+Ans[k<<|];return;
}
inline int Query(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return Ans[k];
pushdown(k,l,r);
int mid=l+r>>,res=;
if(x<=mid) res+=Query(k<<,l,mid,x,y);
if(mid<y) res+=Query(k<<|,mid+,r,x,y);
Ans[k]=Ans[k<<]+Ans[k<<|];return res;
}
inline void add(int x,int y,int w){
qx[++tot]=x+n,qy[tot]=y+n,qw[tot]=w;
Modify(,,*n,x+n,y+n,w);return;
}
inline int Q(int x,int y){
return Query(,,*n,x+n,y+n);
}
}segment2;
int Ans;
signed main(){
// freopen("1.in","r",stdin);
n=read();read();
for(int i=;i<=n;i++) a[i]=read(),ve[a[i]].push_back(i);
for(int i=;i<n;i++){
int siz=ve[i].size();
if(!siz) continue;
int l=,r=-;
segment1.clear();
segment2.clear();
segment1.add(,,,);
segment2.add(,,);
for(int j=;j<siz;j++){
int u=ve[i][j];
r=u-;
if(j!=) l=ve[i][j-]+;
else l=;
if(l<=r){
int L=-l+j*,R=-r+j*;
if(L>R) swap(L,R);
Ans+=segment2.Q(-n,L-)*(R-L+);
Ans+=R*segment2.Q(L,R);
Ans-=segment1.Q(L,R);
segment1.add(L,R,L,);
segment2.add(L,R,);
}
int Psum=-u+*(j+);
Ans+=segment2.Q(-n,Psum-);
segment1.add(Psum,Psum,Psum,);
segment2.add(Psum,Psum,);
}
l=ve[i][siz-]+,r=n;
if(l<=r){
int L=-l+siz*,R=-r+siz*;
if(L>R) swap(L,R);
Ans+=segment2.Q(-n,L-)*(R-L+);
Ans+=R*segment2.Q(L,R);;
Ans-=segment1.Q(L,R);
segment1.add(L,R,L,);
segment2.add(L,R,);
}
}printf("%lld\n",Ans);return ;
}

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

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

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

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

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

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

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

  4. 【bzoj5110】Yazid的新生舞会

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

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

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

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

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

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

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

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

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

  9. [BZOJ5110]Yazid的新生舞会

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

随机推荐

  1. html area标签 语法

    html area标签 语法 作用:带有可点击区域的图像映射 说明:<img> 中的 usemap 属性可引用 <map> 中的 id 或 name 属性(由浏览器决定),所以 ...

  2. SQL高级教程-TOP 子句

    TOP 子句 TOP 子句用于规定要返回的记录的数目. 对于拥有数千条记录的大型表来说,TOP 子句是非常有用的. 注释:并非所有的数据库系统都支持 TOP 子句. SQL Server 的语法: S ...

  3. mac 下 git log 退出方法

    英文状态下按 Q (大小写无论)即可.

  4. ZooKeeper设置开机启动

    1 在init.d目录下新建脚本文件 进入到/etc/rc.d/init.d目录下,命令是: cd    /etc/rc.d/init.d 新建一个名为zookeeper的文件,命令是: touch ...

  5. Redis单节点部署

    安装Redis 由于REDIS使用单线程处理请求,CPU的快慢最对REDIS的性能有较大影响,官方建议INTEL的CPU,其效率能比AMD高一倍左右. 下载Redis:wget http://down ...

  6. 使用mysql以及连接数据库

    MySQL Table of Contents 1. 安装与配置 2. 数据库与账户 3. 用户跟权限 4. 常用命令 5. 表的创建 6. 数据类型 7. 主键约束 8. 表的修改 9. 引擎(En ...

  7. Spring MVC过滤器HiddenHttpMethodFilter

    浏览器form表单只支持GET与POST请求,而DELETE.PUT等method并不支持,spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET.POST.PUT ...

  8. ffmpeg摄像头推流

    ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -preset:v ultrafast -tune:v z ...

  9. Python学习之==>模块结构调整

    一.为什么要进行模块结构调整 当一个脚本中有大量的配置.方法及接口时,脚本显得十分臃肿,可读性很差.为了提高代码的易读性,可以将一个繁杂的脚本根据不同的功能放在不同的目录下分类管理,这整个过程叫做模块 ...

  10. 干货 | 剑指offer系列文章汇总

    下面是名企面试中经常会出现的面试题目,大家可以戳相应的题目查看题目细节,其答案会在紧接着的后一篇中出现  剑指offer系列  始 剑指offer—灯管问题(1)  剑指offer—10人电梯(2)  ...