洛谷题面传送门

一个线性做法。

\(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 的新生舞会 的线性做法的更多相关文章

  1. 洛谷 P4062 - [Code+#1]Yazid 的新生舞会(权值线段树)

    题面传送门 题意: 给出一个序列 \(a\),求 \(a\) 有多少个子区间 \([l,r]\),满足这个区间中出现次数最多的数出现次数 \(>\dfrac{r-l+1}{2}\) \(1 \l ...

  2. luogu P4062 [Code+#1]Yazid 的新生舞会(线段树+套路)

    今天原来是平安夜啊 感觉这题是道好题. 一个套路枚举权值\(x\),把权值等于\(x\)的设为1,不等于的设为-1,然后问题转化为多少个区间权值和大于. 发现并不是很好做,还有一个套路,用前缀和查分来 ...

  3. P4062 [Code+#1]Yazid 的新生舞会

    思路:分治 提交:2次 错因:数组开小 题解: 我们枚举一下众数\(x\). 设\(s[n]=\sum_{i=1}^n [a[i]==x]\) 那么对于区间\((l,r]\),有\(s[r]-s[l] ...

  4. 【线段树】【P4062】 [Code+#1]Yazid 的新生舞会

    Description 给定一个长度为 \(n\) 的序列,求有多少子区间满足区间众数严格大于区间长度的一半.如果区间有多个出现次数最多且不同的数则取较小的数为众数. Limitation 对于全部的 ...

  5. [题解] [Code+#1]Yazid 的新生舞会

    题面 题解 upd : \(cnt_i\) 代表值为 \(i\) 的个数 我们可以暴力枚举众数 \(k\) 把等于 \(k\) 的赋值成 1 , 不等于 \(k\) 的赋值成 -1 这样原序列就变成了 ...

  6. 【BZOJ5110】[CodePlus2017]Yazid 的新生舞会 线段树

    [BZOJ5110][CodePlus2017]Yazid 的新生舞会 Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一 ...

  7. BZOJ.5110.[CodePlus2017]Yazid 的新生舞会(线段树/树状数组/分治)

    LOJ BZOJ 洛谷 又来发良心题解啦 \(Description\) 给定一个序列\(A_i\).求有多少个子区间,满足该区间众数出现次数大于区间长度的一半. \(n\leq5\times10^5 ...

  8. bzoj5110: [CodePlus2017]Yazid 的新生舞会

    Description Yazid有一个长度为n的序列A,下标从1至n.显然地,这个序列共有n(n+1)/2个子区间.对于任意一个子区间[l,r] ,如果该子区间内的众数在该子区间的出现次数严格大于( ...

  9. 洛谷UVA12995 Farey Sequence(欧拉函数,线性筛)

    洛谷题目传送门 分数其实就是一个幌子,实际上就是求互质数对的个数(除开一个特例\((1,1)\)).因为保证了\(a<b\),所以我们把要求的东西拆开看,不就是\(\sum_{i=2}^n\ph ...

随机推荐

  1. NC105 二分查找法

    二分查找(一) 二分查找看似简单,但是有很多的细节要注意. 题目是牛客NC105,找到有序数组中第一个大于或者等于所查找的数字. 初步写了如下的代码: class Solution { public: ...

  2. 乘风破浪,遇见最美Windows 11之新微软商店(Microsoft Store)生态 - 安卓(Android™)开发体验指南

    什么是Windows 11的安卓(Android)应用 2021年6月25日,微软召开线上发布会,对外宣告下一代Windows操作系统Windows 11,Windows 11为用户重新打造的Micr ...

  3. 2021.9.9考试总结[NOIP模拟50]

    T1 第零题 神秘结论:从一个点满体力到另一个点的复活次数与倒过来相同. 于是预处理出每个点向上走第$2^i$个死亡点的位置,具体实现可以倍增或二分. 每次询问先从两个点同时向上倍增,都转到离$LCA ...

  4. Linux下Zabbix5.0 LTS监控基础原理及安装部署(图文教程)

    Zabbix 是什么? zabbix 是一个基于 Web 界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.通过 C/S 模式采集数据,通过 B/S 模式在 Web 端展示和配置,能监视 ...

  5. 利用Microsoft Graph开发微软的Exchange Calendar会议、Team

    Microsoft Graph是什么? Microsoft Graph 是 Microsoft 365 中通往数据和智能的网关. 它提供统一的可编程模型,可用于访问 Microsoft 365.Win ...

  6. PCIE笔记--PCIe错误定义与分类

    转载地址:http://blog.chinaaet.com/justlxy/p/5100057782 前面的文章提到过,PCI总线中定义两个边带信号(PERR#和SERR#)来处理总线错误.其中PER ...

  7. 原串反转 牛客网 程序员面试金典 C++ Python

    原串反转 牛客网 程序员面试金典 C++ Python 题目描述 请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量). 给定一个string iniS ...

  8. POJ 2584 T-Shirt Gumbo(二分图最大匹配)

    题意: 有五种衣服尺码:S,M,L,X,T N个人,每个人都有一个可以穿的衣服尺码的范围,例:SX,意思是可以穿S,M,L,X的衣服. 给出五种尺码的衣服各有多少件. 如果可以满足所有人的要求,输出 ...

  9. mysql登录后重置root密码的步骤

    mysql重置root密码. 方法一: 编辑配置文件 /etc/my.cnf ,在[mysqld]后面任意一行添加"skip-grant-tables"用来跳过密码验证 接下来我们 ...

  10. RocketMQ Consumer 启动时都干了些啥?

    可能我们对 RocketMQ 的消费者认知乍一想很简单,就是一个拿来消费消息的客户端而已,你只需要指定对应的 Topic 和 ConsumerGroup,剩下的就是只需要: 接收消息 处理消息 就完事 ...