洛谷 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 ...
随机推荐
- javascript-jquery对象的属性处理
1.attr()方法:获取元素某个属性的值. $("img").attr("title");//获得第一个<img>元素的title属性 $(&qu ...
- 8.5(337)——树形dp
将题目进行翻译,就是遍历二叉树算出最大权值,在遍历过程中,不能同时选择两个相连的节点. 第一种子问题的构造,是以爷爷--父亲--孙子的"三代"节点一同构造的,将最优子问题的结构定义 ...
- [对对子队]会议记录5.19(Scrum Meeting6)
今天已完成的工作 吴昭邦 工作内容:搭建第9关 相关issue:搭建关卡7.8.9 相关签入:feat: 第9关能够通过 何瑞 工作内容:搭建第9关 相关issue:搭建关卡7.8 ...
- PWM通过RC低通滤波器模拟DAC
当我们电路需要DAC而单片机并没有DAC外设时,则可采用PWM通过RC低通滤波器来模拟实现DAC功能. RC低通滤波器 当采用低通滤波器模拟DAC时,PWM频率应远大于RC低通滤波电路的截止频率fc= ...
- [LGP2758]编辑距离
目录 题目 题目描述 输入格式 输出格式 输入输出样例 题目分析 状态转移方程 初始状态 结束状态 Code 题目 题目描述 设A和B是两个字符串.我们要用最少的字符操作次数,将字符串A转换为字符串B ...
- 局域网(以太网与IEEE 802.3、IEEE 802.11、)
文章转自:https://blog.csdn.net/weixin_43914604/article/details/105016637 学习课程:<2019王道考研计算机网络> 学习目的 ...
- STP生成树协议在二层环境中的应用
一 STP简介 1.单词: rstp快速生成树协议 filter过滤 protection保护 2.作用: 通过阻塞特定接口来防止二层交换环路,从而做到既可以提高网络可靠性的同时又能避免环路带来的问题 ...
- SpringMVC配置知识点
SpringMVC原生知识点 通过idea新建一个SpringMVC的Project(新建普通的项目就行了) 填写完之后Finish就行了 (实际开发不会这么用,这么做是为了理解!) 然后就是Spri ...
- LeetCode刷题 树专题
树专题 关于树的几个基本概念 1 树的节点定义 2 关于二叉树的遍历方法 2.1 前序遍历 2.2 中序遍历 2.3 后序遍历 2.4 层序遍历 3 几种常见的树介绍 3.1 完全二叉树 3.2 二叉 ...
- Linux NameSpace (目录)
1. User Namespace 详解 2. Pid Namespace 详解 3. Mnt Namespace 详解 4. UTS Namespace 详解 5. IPC Namespace 详解 ...