ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P5501 [LnOI2019]来者不拒,去者不追

2022-02-17 11:04:28  阅读:169  来源: 互联网

标签:fxx LnOI2019 int long P5501 去者 ans ask id


来者不拒,去者不追

考虑莫队,挪动指针往区间 \([l,r]\) 中加入一个数 \(x\),产生的贡献就是 \(比 x 大的数之和 + 比 x 小的数的个数\times x +x\)
然后这样是 \(O(n\sqrt m \log n\)) 的

发现如果不加最后那个 \(x\) 的话就是可差分的(等于对 \([1,r]\) 的贡献减去对 \([1,l]\) 的贡献),于是考虑二次离线
预处理简单,二次离线的时候会产生 \(O(n)\) 此插入一个数的修改和 \(O(n\sqrt n)\) 此询问上面的那两个信息
在值域上分块做到 \(O(1)\) 查询,\(O(\sqrt n)\) 修改即可

最后输出前把那个 \(x\) 加回来

#define N 500006
#define B 707
#define V 100000
#define VB 316
int n,m;
struct Ask{
	int l,r,id;
};
Ask ask[N];
struct Node{
	int L,R,i,k;
};
std::vector<Node>change[N];
int belong[N];
long long a[N];
long long bsum[VB+6],sum[V+6],bnum[VB+6],num[V+6];
long long fxx[N],ans[N];
inline void pre(){
	for(int i=1;i<=V;i++) belong[i]=(i-1)/VB+1;
	for(int i=1;i<=n;i++){
		fxx[i]=bsum[belong[a[i]]]+sum[a[i]]+a[i]*(bnum[belong[a[i]]]+num[a[i]]);
		for(int j=a[i]-1;belong[j]==belong[a[i]];j--) sum[j]+=a[i];
		for(int j=belong[a[i]]-1;j;j--) bsum[j]+=a[i];
		for(int j=a[i]+1;belong[j]==belong[a[i]];j++) num[j]++;
		for(int j=belong[a[i]]+1;j<=belong[V];j++) bnum[j]++;
	}
	for(int i=1;i<=n;i++) fxx[i]+=fxx[i-1];
	std::memset(bsum,0,sizeof bsum);std::memset(sum,0,sizeof sum);std::memset(bnum,0,sizeof bnum);std::memset(num,0,sizeof num);
}
int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++) a[i]=read(),belong[i]=(i-1)/B+1;
	for(int i=1;i<=m;i++) ask[i].l=read(),ask[i].r=read(),ask[i].id=i;
	std::sort(ask+1,ask+1+m,[](const Ask &a,const Ask &b){return belong[a.l]==belong[b.l]?a.r<b.r:a.l<b.l;});
	pre();
	for(int l=1,r=0,L,R,i=1;i<=m;i++){
		L=ask[i].l;R=ask[i].r;
		if(r<R) change[l-1].push_back({r+1,R,i,-1}),ans[ask[i].id]+=fxx[R]-fxx[r],r=R;
//		while(r<ask[i].r) ans[ask[i].id]+=fxx[++r];
		if(l>L) change[r].push_back({ask[i].l,l-1,i,1}),ans[ask[i].id]-=fxx[l-1]-fxx[L-1],l=L;
//		while(l>ask[i].l) ans[ask[i].id]-=fxx[--l];
		if(r>R) change[l-1].push_back({ask[i].r+1,r,i,1}),ans[ask[i].id]-=fxx[r]-fxx[R],r=R;
//		while(r>ask[i].r) ans[ask[i].id]-=fxx[r--];
		if(l<L) change[r].push_back({l,ask[i].l-1,i,-1}),ans[ask[i].id]+=fxx[L-1]-fxx[l-1],l=L;
//		while(l<ask[i].l) ans[ask[i].id]+=fxx[l++];
	}
	for(int i=1;i<=n;i++){
		for(int j=a[i]-1;belong[j]==belong[a[i]];j--) sum[j]+=a[i];
		for(int j=belong[a[i]]-1;j;j--) bsum[j]+=a[i];
		for(int j=a[i]+1;belong[j]==belong[a[i]];j++) num[j]++;
		for(int j=belong[a[i]]+1;j<=belong[V];j++) bnum[j]++;
		for(const Node &x:change[i]){
			register long long tmp=0;
			for(int j=x.L;j<=x.R;j++) tmp+=bsum[belong[a[j]]]+sum[a[j]]+a[j]*(bnum[belong[a[j]]]+num[a[j]]);
			ans[ask[x.i].id]+=x.k*tmp;
		}
	}
	for(int i=1;i<=n;i++) a[i]+=a[i-1];
	for(int i=1;i<=m;i++) ans[ask[i].id]+=ans[ask[i-1].id];
	for(int i=1;i<=m;i++) ans[ask[i].id]+=a[ask[i].r]-a[ask[i].l-1];
	for(int i=1;i<=m;i++) writeEN(ans[i]);
	return RET;
}

标签:fxx,LnOI2019,int,long,P5501,去者,ans,ask,id
来源: https://www.cnblogs.com/suxxsfe/p/15903612.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有