[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 ...
随机推荐
- RMQ问题(超详细!!!)
一.简介 RMQ是询问某个区间内的最大值或最小值,暴力解法对每个询问区间用循环找最值,当n.q>10000会TLE. 常用RMQ的求解方法——ST算法. ST算法通常用在要多次询问一些区间的最值 ...
- Java动态代理实现方式一
Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理 实现方式一:静态代理 静态代理方式的优点 静态代理方式的缺点 Java动态代理实现方式一:InvocationHandler Ja ...
- 【牛客】路径计数机 (树形dp 前缀和)
题目描述 有一棵n个点的树和两个整数p, q,求满足以下条件的四元组(a, b, c, d)的个数: 1.$1\leq a,b,c,d \leq n$ 2.点a到点b的经过的边数为p. 3.点c ...
- 树形dp专题总结
树形dp专题总结 大力dp的练习与晋升 原题均可以在网址上找到 技巧总结 1.换根大法 2.状态定义应只考虑考虑影响的关系 3.数据结构与dp的合理结合(T11) 4.抽直径解决求最长链的许多类问题( ...
- C语言之“字符”与“字符串”之间的区别解析
在C语言中,“字符”与“字符串”之间,是有区别的.这一篇文章中,我们将介绍一下,在C语言中的“字符”与“字符串”,它们之间的区别. 首先,一个很明显的区别是: “字符”,使用单引号作为定界符,而“字符 ...
- Linux中git用https连接时不用每次输入密码
应用场景: 比如每天凌晨执行crontab对应的项目部署脚本(使用git作为项目的版本控制). 如果不这样做会怎么样? 每次部署都要git clone并输入对应的用户名和密码,需要人工.这样就显得很不 ...
- js浮点数精度丢失问题及如何解决js中浮点数计算不精准
js中进行数字计算时候,会出现精度误差的问题.先来看一个实例: console.log(0.1+0.2===0.3);//false console.log(0.1+0.1===0.2);//true ...
- 数据接口-免费版(股票数据API)
获取股票数据的源头主要有:数据超市.雅虎.新浪.Google.和讯.搜狐.ChinaStockWebService.东方财富客户端.证券之星.网易财经. 数据超市 2016年5月6日更新.根据最近频繁 ...
- 暑假gosh计划
[要参与的事项]: 1.大创 2.CTF 3.ACM 4.自己的巴拉巴拉巴 [基本目标]: 1.大创 学完一本Java入门教材 学习Material Design,了解典型交互,进行ui初步设计 2. ...
- Spring Boot使用Html
1.引入模板thymeleaf <dependency> <groupId>org.springframework.boot</groupId> <artif ...