[loj 6253] Yazid的新生舞会
(很久之前刷的题现在看起来十分陌生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的新生舞会的更多相关文章
- [LOJ 6253] Yazid 的新生舞会
link $solution:$ 不知道为什么别人的代码能写的非常短,难道就是写差分的好处? 这种题肯定是算每个众数的贡献,考虑通过暴力众数求出个数. 现在考虑众数 $x$ ,则在序列 $a$ 中将等 ...
- 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会 线段树
[BZOJ5110][CodePlus2017]Yazid 的新生舞会 Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一 ...
- bzoj5110: [CodePlus2017]Yazid 的新生舞会
Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一个子区间[l,r] ,如果该子区间内的众数在该子区间的出现次数严格大于( ...
- 【bzoj5110】Yazid的新生舞会
这里是 $THUWC$ 选拔时间 模拟赛的时候犯 $SB$ 了,写了所有的部分分,然后直接跑过了 $4$ 个大样例(一个大样例是一个特殊情况)…… 我还以为我非常叼,部分分都写对了,于是就不管了…… ...
- BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)
LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...
- 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会
题解: 没笔的时候我想了一下 发现如果不是出现一半次数而是k次,并不太会做 然后我用前缀和写了一下发现就是维护一个不等式: 于是就可以随便维护了
- 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)
学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2 ...
- 【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap
题目描述 求一个序列所有的子区间,满足区间众数的出现次数大于区间长度的一半. 输入 第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型.数据类型的作用将在子任务中说明. 第二行n个用 ...
- [BZOJ5110]Yazid的新生舞会
题目大意: 给你一个长度为$n(n\leq 5\times 10^5)$的序列$A_{1\sim n}$.求满足区间众数在区间内出现次数严格大于$\lfloor\frac{r-l+1}{2}\rflo ...
随机推荐
- java自动化配置工具 - autoconfig 简介
对于java程序员来说各种各样的配置文件是司空见惯的,比如spring的bean配置,struts的action配置等等.有些配置会随着运行环境的变化而各不相同,最典型的就是jdbc驱动的配置,在开发 ...
- JPA批量插入优化
遇到一个需求是excel数据导入,一次大概会批量插入几万的数据.写完一测奇慢无比. 于是开始打日志,分析代码,发现是插入数据库的时候耗时很长,发现是spring data jpa的原因. 翻看jpa的 ...
- “未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序
一.背景: 开发一个工具的小项目,因为数据少,我就不想安装sqlserver数据库,就用Access数据库. 二.问题: 在客户安装程序的时候,接口访问Access数据库的时候,报错“未在本地计算机上 ...
- Elasticsearch与Solr优缺点比较
Elasticsearch简介 Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助你用前所未有的速度去处理大规模数据. 它可以用于全文搜索,结构化搜索以及分析,也可以将这三者进行组 ...
- 为什么不要使用==比较Integer?
比较Integer的时候,不要用==. 查看Integer的源码,如下: /** * Returns an {@code Integer} instance representing the spec ...
- 命令行利用ffmpeg实现rtmp推流《转》
ffmpeg在以前介绍过,是一个相当强大的工具,我们这次利用它实现rtmp推流(最终推流地址统一为rtmp://127.0.0.1:1935/live/123). 1.首先下载ffmpeg和ffpla ...
- httpcomponents 发送get post请求
引入的包为: <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <de ...
- Comparable接口的使用
功能: Comparable接口可用于对象的排序或者对象的分组 介绍: Comparable接口强行对实现它的类的每个实例进行自然排序,该接口的唯一方法compareTo方法被称为自然比较方法 方法: ...
- 往hbase插入数据,你会选择哪种?
好久,好久没有写个博客了,自从上次封闭开始,到“自闭”,有了一段时间了,哈哈^_^ . 多亏了云桌面的歇菜, 一下午啥都干不了, 突然想到,好久没有写点啥了,就写的,让时间流走有点痕迹吧 _(:з」∠ ...
- 用PMML实现python机器学习模型的跨平台上线
python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...