P4062 [Code+#1]Yazid 的新生舞会(区间绝对众数+分治/树状数组维护高维前缀和)

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

杭电多校懂得都懂

Code1

分治

比较喜欢分治的做法,非常好写。skylee大佬题解


首先对于任何一个区间来说,由于两个端点不确定性非常难以一次性统计多组区间,因为它们没有相似之处。

考虑分治,花费log⁡\loglog的代价使得当前考虑的区间必须经过mid\text{mid}mid,意味着当前区间左端点必须在[l,mid][\text{l},\text{mid}][l,mid]区间内部,而右端点必须在[mid+1,r][\text{mid}+1,\text{r}][mid+1,r]区间内部,这样的区间特殊在一定经过mid使得可以先预处理左端点的一些信息,然后枚举右端点一次性统计多个区间。

首先枚举可能作为区间绝对众数的数v\text vv,然后考虑哪些上述区间能使得该数作为区间的绝对众数。

vl,vr\text{vl},\text{vr}vl,vr分别是可能使v\text vv作为区间[vl,vr][\text{vl},\text{vr}][vl,vr]的绝对众数。
cntvl\text{cnt}_{\text {vl}}cntvlvl→mid\text{vl}\to \text{mid}vlmid 数字v\text vv出现的次数。
cntvr\text{cnt}_{\text {vr}}cntvrmid+1→vr\text{mid}+1\to \text {vr}mid+1vr 数字v\text vv出现的次数。

cntvr+cntvl>12[r−l+1]\text{cnt}_{\text {vr}}+\text{cnt}_{\text {vl}}>\frac{1}{2}[r-l+1]cntvr+cntvl>21[rl+1]
从上面式子可以得出
2cntvl+l−1>r−2cntvr2\text{cnt}_{\text {vl}}+l-1>r-2\text{cnt}_{\text {vr}}2cntvl+l1>r2cntvr

考虑枚举vr\text{vr}vr,我们只需要统计有哪些左端点vl\text{vl}vl满足上面式子即可,显然可以预处理+前缀和一次性统计。


还有一个问题就是哪些数可能是区间的绝对众数?

如果一个数vvv是区间[vl,vr][\text{vl},\text{vr}][vl,vr]的绝对众数,那么它一定是区间[vl,mid][\text{vl},\text{mid}][vl,mid]以及[mid+1,vr][\text{mid}+1,\text{vr}][mid+1,vr]的绝对众数,于是可以提前预处理。

显然能够满足上述条件作为区间绝对众数的种类不会很多。上面大佬题解说是log⁡\loglog量级的。

时间复杂度O(nlog⁡2n)O(n\log ^2n)O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
const int N=500010;
int a[N],n;
ll ans;
int b[N],cnt;
int mp[N],in[N];
int num[2*N];
void solve(int l,int r)
{if(l==r) return ans++,void();int mid=l+r>>1;solve(l,mid),solve(mid+1,r);cnt=0;for(int i=mid;i>=l;i--){mp[a[i]]++;if(mp[a[i]]>(mid-i+1)/2){if(in[a[i]]) continue;in[a[i]]=1;b[++cnt]=a[i];}}for(int i=l;i<=mid;i++) mp[a[i]]--;for(int i=mid+1;i<=r;i++){mp[a[i]]++;if(mp[a[i]]>(i-mid)/2){if(in[a[i]]) continue;in[a[i]]=1;b[++cnt]=a[i];}}for(int i=mid+1;i<=r;i++) mp[a[i]]--;for(int i=l;i<=r;i++) in[a[i]]=0;//for(int i=1;i<=cnt;i++) cout<<b[i]<<" \n"[i==cnt];for(int i=1;i<=cnt;i++){int cur=0;int L=3*n,R=0;for(int j=mid;j>=l;j--){if(a[j]==b[i]) cur++;num[2*cur+j-1]++;L=min(L,2*cur+j-1);R=max(R,2*cur+j-1);}for(int i=R;i>L;i--) num[i-1]+=num[i];cur=0;for(int j=mid+1;j<=r;j++){if(a[j]==b[i]) cur++;ans+=(num[max(L,j-2*cur+1)]);}for(int i=R;i>=L;i--) num[i]=0;}}
int main()
{n=rd();rd();for(int i=1;i<=n;i++) a[i]=rd();solve(1,n);printf("%lld\n",ans);return 0;
}

Code2

OMG_wc大佬题解
Zechariah大佬题解

其实赛时的将此问题转化成了下面的问题:如何求小于一段公差为1的等差数列的个数?

  • 求在a1→na_{1\to n}a1n中求小于xxx的个数,小于x+1x+1x+1的个数,小于x+2x+2x+2的个数,小于x+kx+kx+k的个数把他们累加。

然后就死了???这不就是前缀和然后区间询问吗?wtcl

开个桶,然后做一个前缀和,然后就是个区间询问[x,x+k][x,x+k][x,x+k]的问题。。。


此题首先记录每个数出现的位置,单独考虑每个数作为区间的绝对众数。
不妨设当前考虑的数为v\text vv

v\text vv能作为区间(L,R](\text L,\text R](L,R]的众数的充要条件是
cntR−cntL>R−L2\text{cnt}_{\text R}-\text{cnt}_{\text L}>\frac {\text R-\text L}{2}cntRcntL>2RL

2cntL−L<2cntR−R,L<R2\text{cnt}_{\text L}-\text L<2\text{cnt}_{\text R}-\text R ,\text{L}<\text R 2cntLL<2cntRR,L<R

bL=2cntL−L\text b_{\text L}=2\text{cnt}_{\text L}-\text LbL=2cntLL

于是转化成二维偏序:
L<RbL<bR\text{L}<\text R \\ \text b_{\text L}<\text b_{\text R}L<RbL<bR

显然我们枚举右端点,用个树状数组就可以统计,但是复杂度不行。

观察每个数出现的位置将整个区间划分为下面模式
[1,…)[…)[…)[…,n+1)\color{blue}[1,\dots)[\dots)\color{red}[\dots)\color{black}[\dots,\text{n+1}) [1,)[)[)[,n+1)
上面)))代表的就是该数出现的位置。
对于每个[…)\color{red}[\dots)[)内部bi\text b_{\text i}bi是单调下降,且公差为1,显然当区间右端点在此区间内部时,区间左端点不可能在其内部。换句话说就是只有前面的即[1,…)[…)\color{blue}[1,\dots)[\dots)[1,)[)可能对区间右端点在[…)\color{red}[\dots)[)产生贡献。

而且重要的是[…)\color{red}[\dots)[)bj\text b_{\text j}bj连续的,即对于每一个[…)\color{red}[\dots)[)bj\text b_{\text j}bj我们需要在[1,…)[…)\color{blue}[1,\dots)[\dots)[1,)[)找到bi<bj\text b_{\text i}<\text b_{\text j}bi<bj,显然就是最开始那个问题,只需要求个前缀和然后区间询问即可。

每次过考虑[…)\color{red}[\dots)[)后进行区间修改,将[…)\color{red}[\dots)[)内部的bj\text b_{\text j}bj插入数据结构中。


区间修改+前缀和区间询问
树状数组的话可以把差分转化为单点修改,那么本次要做到区间询问就意味着要用树状数组维护三维前缀和
∑i=1n∑j=1i∑k=1jdk=12[(n2+3n+2)∑i=1ndi−(2n+3)∑i=1ni⋅di+∑i=1ni2⋅di]\sum_{i=1}^{n}\sum_{j=1}^i\sum_{k=1}^jd_k=\frac{1}{2}[(n^2+3n+2)\sum_{i=1}^nd_i-(2n+3)\sum_{i=1}^ni·d_i+\sum_{i=1}^ni^2·d_i] i=1nj=1ik=1jdk=21[(n2+3n+2)i=1ndi(2n+3)i=1nidi+i=1ni2di]

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;T fg=1;char ch=getchar();while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res*fg;
}
const int N=500010;
int a[N],n;
vector<int> loc[N];
ll c0[N<<1],c1[N<<1],c2[N<<1];
void update(int k,ll v,int n)
{ll i=k*v,ii=1ll*k*k*v;while(k<=n){c0[k]+=v;c1[k]+=i;c2[k]+=ii;k+=k&-k;}
}
ll qsum(int k)
{ll ans=0;ll k1=1ll*k*k+3*k+2,k2=2*k+3;while(k){ans+=k1*c0[k]-k2*c1[k]+c2[k];k-=k&-k;}return ans>>1;
}
int main()
{n=rd();rd();for(int i=1;i<=n;i++) a[i]=rd(),loc[a[i]].push_back(i);ll ans=0;const int Bs=n+1;for(int i=0;i<n;i++){if(loc[i].empty()) continue;int pre=0;loc[i].push_back(n+1);for(int j=0;j<loc[i].size();j++){int R=2*j-pre+Bs,L=2*j-(loc[i][j]-1)+Bs;ans+=qsum(R-1)-qsum(max(0,L-2));// 严格小于update(L,1,n<<1|1);update(R+1,-1,n<<1|1);pre=loc[i][j];}pre=0;for(int j=0;j<loc[i].size();j++){int R=2*j-pre+Bs,L=2*j-(loc[i][j]-1)+Bs;update(L,-1,n<<1|1);update(R+1,+1,n<<1|1);pre=loc[i][j];}}printf("%lld\n",ans);return 0;
}

要加油哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题霸 [判断回文] C++题解/答案

牛客题霸 [判断回文] C题解/答案 题目描述 给定一个字符串&#xff0c;请编写一个函数判断该字符串是否回文。如果回文请返回true&#xff0c;否则返回false。 题解&#xff1a; 左右两端同时向中间缩 代码&#xff1a; class Solution { public:/*** 代码中的类名、方法…

AC自动机:例题与机制详解

介绍 AC自动机是kmp算法和trie树的结合 大体就是做这样的题用&#xff1a; 可以发现&#xff0c;这题和trie树的区别是把多个单词往一篇文章匹配&#xff0c;而trie恰好相反 匹配的时候其实就是判断子串&#xff0c;所以又用到了kmp 定义失配指针nxt[i]&#xff1a;表示root到…

.NET Core实战项目之CMS 第七章 设计篇-用户权限极简设计全过程

写在前面这篇我们对用户权限进行极简设计并保留其扩展性。首先很感谢大家的阅读&#xff0c;前面六章我带着大家快速入门了ASP.NET Core、ASP.NET Core的启动过程源码解析及配置文件的加载过程源码解析并引入依赖注入的概念、Git的快速入门、Dapper的快速入门、Vue的快速入门。…

P4428-[BJOI2018]二进制【树状数组,set】

正题 题目链接:https://www.luogu.com.cn/problem/P4428 题目大意 长度为nnn的0/10/10/1串要求支持 修改一个位置求区间[l,r][l,r][l,r]有多少个子区间重排后的二进制数可以被三整除 1≤n≤1051\leq n\leq 10^51≤n≤105 解题思路 首先有22k%31(k∈Z)2^{2k}\%31(k\in Z)22k…

2021“MINIEYE杯”中国大学生算法设计超级联赛(5)Random Walk 2(推式子+矩阵逆+矩阵乘)

Random Walk 2 【2.4】Gauss-Jordan消元法求矩阵的逆 高斯消元求矩阵的逆&#xff0c;伴随单位矩阵一起消元即可。 [A,I]→[I,A−1][\text A,\text I]\to [\text I,\text A^{-1}][A,I]→[I,A−1] 移项变形&#xff0c;后就是个矩阵的逆&#xff0c;为啥赛时不写&#xff1f;&a…

牛客题霸 [顺时针旋转矩阵] C++题解/答案

牛客题霸 [顺时针旋转矩阵] C题解/答案 题目描述 有一个NxN整数矩阵&#xff0c;请编写一个算法&#xff0c;将矩阵顺时针旋转90度。 给定一个NxN的矩阵&#xff0c;和矩阵的阶数N,请返回旋转后的NxN矩阵,保证N小于等于300。 题解&#xff1a; 根据题目要求&#xff0c;先…

数论:扩展欧几里德(洛谷P1516 青蛙的约会)

欧几里德 基本思想&#xff1a;gcd(q,r)gcd(r,q%r); 证明&#xff0c;设q、r的最大公因数为a&#xff0c;则qxa&#xff0c;rya&#xff0c;xy互质 不妨设x>y&#xff08;显然如果小于会在一次gcd运算后交换&#xff09; 则q%r&#xff08;x%y&#xff09;*a 显然,其与r的最…

CF802O-April Fools‘ Problem(hard)【wqs二分,优先队列】

正题 题目链接:https://www.luogu.com.cn/problem/CF802O 题目大意 nnn天每条有aia_iai​和bib_ibi​。 每条可以花费aia_iai​准备至多一道题&#xff0c;可以花费bib_ibi​打印至多一道准备好了的题。 求准备kkk道题最少要花费多少。 1≤k≤n≤51051\leq k\leq n\leq 5\ti…

2021牛客暑期多校训练营3 G-Yu Ling(Ling YueZheng) and Colorful Tree(cdq分治)

G-Yu Ling(Ling YueZheng) and Colorful Tree HOWARLI题解 大致做法就是首先考虑哪些修改可能影响询问&#xff0c;当修改点权是询问的倍数时才可能影响询问。于是考虑把他们放在一起。 首先每次枚举每种询问的倍数&#xff0c;把这些修改和当前询问放在一起&#xff0c;由于…

参加胶东开发者技术大会有感

2015年的时候&#xff0c;也是在12月&#xff0c;我和Bob(https://www.cnblogs.com/nianming/)去北京参加了“全球架构师峰会”&#xff0c;在那次会议上&#xff0c;来自百度、腾讯、阿里巴巴、京东、美团、新浪微博、Twitter等公司的架构师、技术专家们分享了各自在架构方面的…

牛客题霸 [矩阵乘法] C++题解/答案

牛客题霸 [矩阵乘法] C题解/答案 题目描述 给定两个nn的矩阵A和B&#xff0c;求AB。 题解&#xff1a; 都学过矩阵相乘把&#xff0c;[i][k][i][j]*[j][k] 代码&#xff1a; class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&…

专题:数列信息传递问题转化为图论合点问题(ybtoj-数列询问+序列破解)

文章目录前言&#xff1a;一、数列询问&#xff08;取模&#xff09;解析代码二、序列破解&#xff08;奇偶性&#xff09;解析代码thanks for reading&#xff01;前言&#xff1a; 在一个数列a中&#xff0c;对于一个大区间A和组成它的两个小区间a&#xff0c;b&#xff1b;…

CF786C-Till I Collapse【树状数组倍增,优先队列】

正题 题目链接:https://www.luogu.com.cn/problem/CF786C 题目大意 给出一个长度为nnn的序列。 对于每个k∈[1,n]k\in[1,n]k∈[1,n]求将nnn分成最少的段使得每段的长度不同。 1≤ai≤n≤1051\leq a_i\leq n\leq 10^51≤ai​≤n≤105 解题思路 考虑对于一个kkk我们的做法显然…

Docker最全教程——从理论到实战(五)

在笔者参加腾讯容器服务技术交流会时&#xff0c;我们了解到了藏区牧民的目前的生活艰辛状况&#xff0c;因此除了在同事朋友之间推荐其土特产之外&#xff0c;我们也在此进行初步分享&#xff0c;希望略尽绵薄之力&#xff0c;能够帮助到他们&#xff1a;货真价实、确保都是37…

2021牛客暑期多校训练营6 J-Defend Your Country(无向图点双+思维)

无向图联通分量 点u是割点&#xff0c;当且仅当 特判树根&#xff1a;u为树根&#xff0c;且u有多于1棵子树u不为树根&#xff0c;在递归树上u存在子节点v&#xff0c;满足&#xff1a;dfnu≤lowv\text{dfn}_u\leq \text{low}_vdfnu​≤lowv​ 如上图&#xff0c;v想走到u的组…

牛客题霸 [比较版本号] C++题解/答案

牛客题霸 [比较版本号] C题解/答案 题目描述 如果version1 > version2 返回1&#xff0c;如果 version1 < version2 返回-1&#xff0c;不然返回0. 输入的version字符串非空&#xff0c;只包含数字和字符.。.字符不代表通常意义上的小数点&#xff0c;只是用来区分数字…

不止代码:循环比赛(分治)

循环比赛日程表&#xff08;match&#xff09; 【问题描述】 解析 dfs或分治 分治可以不断递归4个小正方形 左上右下为前一半&#xff0c;左下右上后一半 dfs就很无脑了 代码 #include<cstdio> #include<cstring> #include<algorithm> #include<cmath…

P4983-忘情【wqs二分,斜率优化】

正题 题目链接:https://www.luogu.com.cn/problem/P4983 题目大意 给出长度为nnn的序列xxx&#xff0c;记平均数为xˉ\bar{x}xˉ&#xff0c;要求将序列分成mmm段。 每一段[l,r][l,r][l,r]的值为 ((∑ilrxixˉ)xˉ)2xˉ2\frac{((\sum_{il}^rx_i\times \bar x)\bar x)^2}{\bar…

前瞻科技,引领未来!Microsoft Connect(); 2018即将重磅来袭!

怎么用一句话点燃全球的开发者&#xff1f;——Microsoft Connect(); 2018即将重磅来袭&#xff01;每一个观点都能引发科技狂潮&#xff0c;每一项技术都将提速技术进程&#xff0c;由微软举办的 Microsoft Connect(); 2018 即将在太平洋时间12月4日8:30拉开帷幕&#xff01;大…

2021“MINIEYE杯”中国大学生算法设计超级联赛(7)Yiwen with Formula(任意模数FFT)

Yiwen with Formula 溢流眼泪题解 生成函数化成n个多项式乘积&#xff0c;然后分治把他们依次相乘&#xff0c;需要由于指数需要modϕ(998244353)998244353−1\bmod \phi(998244353)998244353-1modϕ(998244353)998244353−1&#xff0c;因此需要任意模数的FFT。。。 常数贼大…