(很久之前刷的题现在看起来十分陌生a)

题意:

给你一个长度为n的序列A,定义一个区间$[l,r]$是“新生舞会的”当且仅当该区间的众数次数严格大于$\frac{r-l+1}{2}$,求有多少子区间是“新生舞会的”。

$n\leq 500000,0\leq A_{i} \leq n-1$

题解:

关于区间众数的问题一般有一个套路:枚举众数后转换成区间求和问题。

考虑枚举众数k,若将序列中等于k的元素视作+1,其他视作-1,那么“新生舞会的“区间必然满足区间之和大于0。

问题变成了如何快速求出有多少个区间之和大于0的子区间。

考虑枚举右端点r并记录前缀和sum,那么要求的就是有多少左端点l满足$sum[l]<sum[r]$

直接用一个线段树维护即可。(树状数组也行,但跟后面的做法无关)

但是这样复杂度是$O(n^2)$的,无法通过本题。

注意到枚举众数后,序列中1的个数的总数是n。

容易发现连续的-1总数也为n,那么我们考虑将一段连续的-1一起考虑。

假设一段-1的起点是l,终点是r,sum值i出现了$cnt(i)$次,那么这段-1作为右端点时对答案的贡献之和就是

$\sum_{i=l}^{r}{\sum_{j=-inf}^{i-1}{cnt(j)}}$

$=\sum_{j=-inf}^{r-1}{\sum_{i=max(j+1,l)}^{r}{cnt(j)}}$

$=(r-l+1)\times{\sum_{i=-inf}^{l-1}{cnt(i)}}+\sum_{i=l}^{r}{(r-i)\times cnt(j)}$

那么直接维护两个线段树表示$cnt(i)$和$cnt(i)\times i$即可。

对于每段-1,统计答案后在其对应值域区间加,然后计算单个1的贡献即可。

复杂度$O(nlogn)$,比较难写,特别是清空线段树时需要注意clear标记的写法。

代码:

#include<bits/stdc++.h>
#define maxn 2000005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long using namespace std;
ll N,M,A[maxn],B[maxn],lz1[maxn<<],lz2[maxn<<];
ll s1[maxn<<],s2[maxn<<],vis[maxn];
vector<ll> pos[maxn]; inline ll read(){
ll x=,f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
} inline void pushup1(ll k){s1[k]=s1[k<<]+s1[k<<|];}
inline void pushdown1(ll len,ll k){
if(k>=(maxn<<)) return;
if(!lz1[k]) return;
if(lz1[k]==-){
s1[k<<]=s1[k<<|]=;
lz1[k<<]=lz1[k<<|]=-;
lz1[k]=; return;
}
if(lz1[k<<]==-) pushdown1(len+>>,k<<),lz1[k<<]=,s1[k<<]=;
if(lz1[k<<|]==-) pushdown1(len>>,k<<|),lz1[k<<|]=,s1[k<<|]=;
lz1[k<<]+=lz1[k],lz1[k<<|]+=lz1[k];
s1[k<<]+=lz1[k]*((len+)>>),s1[k<<|]+=lz1[k]*((len)>>);
lz1[k]=; return;
}
inline ll qry1(ll x,ll y,ll l,ll r,ll k){
pushdown1(r-l+,k);
if(x<=l && r<=y) return s1[k];
ll mid=(l+r)>>,ans=;
if(x<=mid) ans+=qry1(x,y,l,mid,k<<);
if(y>mid) ans+=qry1(x,y,mid+,r,k<<|);
return ans;
}
inline void upd1(ll x,ll y,ll l,ll r,ll k){
pushdown1(r-l+,k);
if(x<=l && r<=y){s1[k]+=(r-l+),lz1[k]++;return;}
ll mid=(l+r)>>;
if(x<=mid) upd1(x,y,l,mid,k<<);
if(y>mid) upd1(x,y,mid+,r,k<<|);
pushup1(k); return;
} inline void pushup2(ll k){s2[k]=s2[k<<]+s2[k<<|];}
inline ll dc(ll x,ll y){return (x+y)*(y-x+)/;}
inline void pushdown2(ll l,ll r,ll k){
if(k>=(maxn<<)) return;
if(!lz2[k]) return;
if(lz2[k]==-){
s2[k<<]=s2[k<<|]=;
lz2[k<<]=lz2[k<<|]=-;
lz2[k]=; return;
}
ll mid=(l+r)>>;
if(lz2[k<<]==-) pushdown2(l,mid,k<<),lz2[k<<]=,s2[k<<]=;
if(lz2[k<<|]==-) pushdown2(mid+,r,k<<|),lz2[k<<|]=,s2[k<<|]=;
lz2[k<<]+=lz2[k],lz2[k<<|]+=lz2[k];
s2[k<<]+=lz2[k]*dc(l,mid),s2[k<<|]+=lz2[k]*dc(mid+,r);
lz2[k]=; return;
}
inline ll qry2(ll x,ll y,ll l,ll r,ll k){
pushdown2(l,r,k);
if(x<=l && r<=y) return s2[k];
ll mid=(l+r)>>,ans=;
if(x<=mid) ans+=qry2(x,y,l,mid,k<<);
if(y>mid) ans+=qry2(x,y,mid+,r,k<<|);
return ans;
}
inline void upd2(ll x,ll y,ll l,ll r,ll k){
pushdown2(l,r,k);
if(x<=l && r<=y){s2[k]+=dc(l,r),lz2[k]++;return;}
ll mid=(l+r)>>;
if(x<=mid) upd2(x,y,l,mid,k<<);
if(y>mid) upd2(x,y,mid+,r,k<<|);
pushup2(k); return;
} inline ll calc(ll x){
ll ans=,sum=N; pos[x].push_back(N+);
for(ll i=;i<pos[x].size()-;i++){
ll lp=pos[x][i]+,rp=pos[x][i+]-;
if(pos[x][i]!=) sum++;
ans+=qry1(,sum-,,M,);
ll tp=qry1(,sum-,,M,);
upd1(sum,sum,,M,),upd2(sum,sum,,M,);
if(lp<=rp){
ll l=sum-(rp-lp+),r=sum-; sum-=(rp-lp+);
ll num=(l==)?:(qry1(,l-,,M,)*(r-l+))+((r)*qry1(l,r-,,M,)-qry2(l,r-,,M,));
ans+=num,upd1(l,r,,M,),upd2(l,r,,M,);
}
}
s1[]=s2[]=,lz1[]=lz2[]=-;
return ans;
} int main(){
N=read(),M=(N<<|); ll not_used=read();
for(ll i=;i<=N;i++) A[i]=read()+;
for(ll i=;i<=N;i++)
if(!vis[A[i]]) vis[A[i]]=,pos[A[i]].push_back();
for(ll i=;i<=N;i++) pos[A[i]].push_back(i);
memset(vis,,sizeof(vis)); ll ans=;
for(ll i=;i<=N;i++)
if(!vis[A[i]]) vis[A[i]]=,ans+=calc(A[i]);
printf("%lld\n",ans);
return ;
}

Yazid

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

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

    link $solution:$ 不知道为什么别人的代码能写的非常短,难道就是写差分的好处? 这种题肯定是算每个众数的贡献,考虑通过暴力众数求出个数. 现在考虑众数 $x$ ,则在序列 $a$ 中将等 ...

  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. linux高性能服务器编程 (七) --Linux服务器程序规范

    第七章 LInux 服务器程序规范 1)linux服务器程序一般以后台进程形式运行.后台进程又称为守护进程,是没有控制终端的,所以不会受到外界的干扰.守护进程的父进程通常是init进程(PID为1的进 ...

  2. linux 线程查看 和 Jvm栈线程ID对应

    一.proc查看进程和线程 该方法是个人最为推荐,也最喜欢的一种方法.进程文件下,有几种方式可以获取目前进程开启的进程数. 查看status文件: # cat /proc//status Name: ...

  3. Java编程思想之六访问权限控制

    访问控制(或隐藏具体实现)与"最初的实现并不恰当"有关. 访问权限控制的等级,从最大权限到最小权限依次为:public,protected,包访问权限(没有关键字)和private ...

  4. idea中如何

    idea工具maven projects里面有9种生命周期,生命周期是包含在一个项目构建中的一系列有序的阶段. 一.最常用的两种打包方法: 1.clean,package(如果报错,很可能就是jar依 ...

  5. Refused to execute script from '...' because its MIME type ('') is not executable, and strict MIME type checking is enabled.

    写在前面 部署项目到weblogic上启动首页访问空白, 浏览器控制台报如题错误. web.xml中把响应头添加防止攻击的报文过滤器禁用就行了(仅仅是为了启动), 以下为转载内容, 可以根据需要自行测 ...

  6. openwrt如何打开linux内核的CONFIG_DEVMEM选项?

    答: 直接在openwrt的make menuconfig中打开CONFIG_KERNEL_DEVMEM选项即可

  7. Xamarin.FormsShell基础教程(4)Shell项目内容列表页面运行效果

    Xamarin.FormsShell基础教程(4)Shell项目内容列表页面运行效果 在创建好Shell解决方案后,就可以运行程序了.本小节将讲解运行后的效果. 内容列表页面 运行程序,初始效果如图1 ...

  8. Java类成员初始化顺序

    类中包含7中成员:1.静态变量 static2.final静态常量 final static3.静态代码块 static{}  //多个代码块顺序执行 4.普通变量5.普通代码块 {}  //多个代码 ...

  9. vscode配置python之settings.json 智能提示

    vscode编写Python的智能提示,搞了好久,参考了各种网上配置,如下,备份方便自己查找. { "workbench.iconTheme": "material-ic ...

  10. centos7.5环境下elasticserch5.6.15集群升级6.8.4

    节点的角色分片: node01 eus_mp_web01 : master,false node,false, ingest,true node02 eus_mp_es01 : master,true ...