洛谷 P4062 - [Code+#1]Yazid 的新生舞会 的线性做法
一个线性做法。
\(n\log n\) 解法可以戳这里查看
首先回顾一下 \(n\log n\) 解法的过程:我们对于每一个数 \(x\),考察其出现位置,设为 \(t_1,t_2,t_3,\cdots,t_c\),然后在这些位置上填上 \(1\),其余位置上填上 \(-1\),然后对序列做一遍前缀和,那么该数对答案的贡献就是前缀和数组中顺序对个数。
直接 \(n\log n\) 求复杂度好像有一点高,怎样优化复杂度呢?首先注意到每个可能成为区间右端点的位置并不多,具体来说,我们猜测它是 \(\mathcal O(c)\) 级别的,其中 \(c\) 为 \(x\) 在原序列中的出现次数,也就是说,我们称前缀和数组为 \(s_k\),那么满足 \(s_k>\min\limits_{j=1}^{k-1}s_j\) 的 \(k\) 的总个数是线性的,因此我们考虑每次计算一个连续递减段的贡献时,暴力向后枚举,直到 \(s_k\le\min\limits_{j=1}^{k-1}s_j\) 即可,这样我们只用实现区间加区间求和(求前缀和),即二阶差分数组上单点加,求二阶差分数组的二阶前缀和即可。
到这里,直接做的复杂度还是带 log 的。我们还能注意到这样一个事实:\(s\) 数组中相邻两个元素之差为 \(\pm 1\)。因此我们考虑动态维护一个指针 \(p\),并动态维护二阶差分数组在 \((-\infty...p-1]\) 处的一阶、二阶前缀和,这样向上移动指针时就加入当前位置的贡献,否则扣除掉当前位置的贡献,这样就不用 BIT 之类的东西维护前缀和。直接移动指针显然会被卡到平方,不过发现对于一段连续递减段,我们假设暴力向后枚举到的位置为 \(q\),那么由于对于 \(q+1\) 到该连续段右端点 \(r\) 这段区间内任意一个 \(k\),都有 \(s_k>\min\limits_{j=1}^{k-1}s_j\),因此这部分的位置在移动指针的过程中肯定是空的,直接一路移下去不加任何贡献即可。这样需要加贡献的部分就是待查询的部分,外加上 \(x\) 的 \(c\) 个出现位置 \(t_1,t_2,t_3,\cdots,t_c\),总个数是 \(\Theta(c)\) 级别的,因此总复杂度就是 \(\Theta(\sum c)=\Theta(n)\)。
话说这题我好像已经写了四种不同复杂度/不同常数的做法了?\(n\sqrt{n\log n}\) 分块,\(n\log n\) 线段树,\(n\log n\) BIT,\(\mathcal O(n)\) 指针维护。看来此题确实是一道很值得研究的题目。
代码(目前洛谷最优解,335ms):
using namespace fastio;
const int MAXN=5e5;
const int DLT=MAXN+3;
int n,fuck,a[MAXN+5],hd[MAXN+5],val[MAXN+5],nxt[MAXN+5],item_n=0;
void ins(int x,int y){val[++item_n]=y;nxt[item_n]=hd[x];hd[x]=item_n;}
int d[MAXN*2+10];
inline void add(int l,int r,int v){d[l+DLT]+=v;d[r+DLT+1]-=v;}
int main(){
read(n);read(fuck);add(0,0,1);ll res=0;
for(int i=1;i<=n;i++) read(a[i]),ins(a[i],i);
for(int v=0;v<n;v++) if(hd[v]){
static int pos[MAXN+5],sum[MAXN+5];int cnt=-1;
pos[++cnt]=n+1;
for(int e=hd[v];e;e=nxt[e]) pos[++cnt]=val[e];
pos[++cnt]=0;reverse(pos,pos+cnt+1);sum[0]=0;
if(cnt==2){res++;continue;}
int mnp=0;ll sum1=0,sum2=0;
for(int i=1;i<=cnt;i++){
int l=sum[i-1]-(pos[i]-pos[i-1]-1),r=sum[i-1]-1;
if(l<=r){
int lim=max(l,mnp);
for(int j=r;j>=lim;j--){
sum2-=sum1;sum1-=d[j+DLT];
res+=sum2;
}
} if(i==cnt) break;
add(l,r,1);sum1+=d[l+DLT];sum2+=sum1;
sum[i]=l+1;add(sum[i],sum[i],1);res+=sum2;
chkmin(mnp,l);
}
for(int i=1;i<cnt;i++) add(sum[i]-1,sum[i-1]-1,-1),add(sum[i],sum[i],-1);
} printf("%lld\n",res);
return 0;
}
洛谷 P4062 - [Code+#1]Yazid 的新生舞会 的线性做法的更多相关文章
- 洛谷 P4062 - [Code+#1]Yazid 的新生舞会(权值线段树)
题面传送门 题意: 给出一个序列 \(a\),求 \(a\) 有多少个子区间 \([l,r]\),满足这个区间中出现次数最多的数出现次数 \(>\dfrac{r-l+1}{2}\) \(1 \l ...
- luogu P4062 [Code+#1]Yazid 的新生舞会(线段树+套路)
今天原来是平安夜啊 感觉这题是道好题. 一个套路枚举权值\(x\),把权值等于\(x\)的设为1,不等于的设为-1,然后问题转化为多少个区间权值和大于. 发现并不是很好做,还有一个套路,用前缀和查分来 ...
- P4062 [Code+#1]Yazid 的新生舞会
思路:分治 提交:2次 错因:数组开小 题解: 我们枚举一下众数\(x\). 设\(s[n]=\sum_{i=1}^n [a[i]==x]\) 那么对于区间\((l,r]\),有\(s[r]-s[l] ...
- 【线段树】【P4062】 [Code+#1]Yazid 的新生舞会
Description 给定一个长度为 \(n\) 的序列,求有多少子区间满足区间众数严格大于区间长度的一半.如果区间有多个出现次数最多且不同的数则取较小的数为众数. Limitation 对于全部的 ...
- [题解] [Code+#1]Yazid 的新生舞会
题面 题解 upd : \(cnt_i\) 代表值为 \(i\) 的个数 我们可以暴力枚举众数 \(k\) 把等于 \(k\) 的赋值成 1 , 不等于 \(k\) 的赋值成 -1 这样原序列就变成了 ...
- 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会 线段树
[BZOJ5110][CodePlus2017]Yazid 的新生舞会 Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一 ...
- BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)
LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...
- bzoj5110: [CodePlus2017]Yazid 的新生舞会
Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一个子区间[l,r] ,如果该子区间内的众数在该子区间的出现次数严格大于( ...
- 洛谷UVA12995 Farey Sequence(欧拉函数,线性筛)
洛谷题目传送门 分数其实就是一个幌子,实际上就是求互质数对的个数(除开一个特例\((1,1)\)).因为保证了\(a<b\),所以我们把要求的东西拆开看,不就是\(\sum_{i=2}^n\ph ...
随机推荐
- 初学Python-day13 文件处理1
IO操作 一.os模块 作用:包含了操作系统的基本功能,提供了非常丰富的用来处理文件和目录的函数或方法. 1.属性 函数名 函数说明 name 获取操作系统的类型 uname 获取操作系统的信息(li ...
- Convolutional Neural Network-week2编程题1(Keras tutorial - 笑脸识别)
本次我们将: 学习到一个高级的神经网络的框架,能够运行在包括TensorFlow和CNTK的几个较低级别的框架之上的框架. 看看如何在几个小时内建立一个深入的学习算法. 为什么我们要使用Keras框架 ...
- Scrum Meeting 0607
零.说明 日期:2021-6-7 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 重新设计产品 ...
- mongodb的简单查询
此篇文章简单的记录一下mongodb 的简单查询操作. 一.数据准备: db.persons.insertMany([ {'userId':1,name:'张三','age':20,'scores': ...
- Noip模拟43 2021.8.18
T1 地一体 可以树形$dp$,但考场没写出来,只打了没正确性的贪心水了$30$ 然后讲题的时候B哥讲了如何正确的贪心,喜出望外的学习了一下 不难发现 每次士兵都会直接冲到叶子节点 从深的点再返回到另 ...
- 所驼门王的宝藏(Tarjan)
题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...
- Logic strength modeling
7.9 Verilog HDL提供了信号争用.双向通过门.电阻式MOS器件.动态MOS.电荷共享的精确建模,并通过允许标量净信号值具有全范围的未知值和不同强度级别或强度级别的组合来实现其他依赖于技术的 ...
- {% csrf_token %} 原理和作用 (踩坑必看)
本博客已暂停更新,请转自新博客 https://www.whbwiki.com/320.html 继续阅读 简介 在django中我们需要在templates的form中加入{%csrf_token% ...
- Flink 实践教程 - 入门(4):读取 MySQL 数据写入到 ES
作者:腾讯云流计算 Oceanus 团队 流计算 Oceanus 简介 流计算 Oceanus 是大数据产品生态体系的实时化分析利器,是基于 Apache Flink 构建的具备一站开发.无缝连接. ...
- 站长管理服务器必读:Ftp、Ftps与Sftp三兄弟的不同与区别以及部署全指引
文章标题: 站长管理服务器必读:Ftp.Ftps与Sftp三兄弟的不同与区别以及部署全指引 关键字 : ftp,sftp,freesshd,ftps 文章分类: 教程 创建时间: 2020年3月23日 ...