首页 > 其他分享 >[NOI2020] 时代的眼泪

[NOI2020] 时代的眼泪

时间:2023-06-25 12:11:56浏览次数:29  
标签:时代 leftarrow int sum id NOI2020 qr 眼泪 ql

分块。设分出来左散块 \(A_1\),中间块 \(B_1,\cdots,B_k\),右散块 \(A_2\)。那么贡献有 \(A_1\leftarrow A_1\) 即散块对自己,\(A_1\leftarrow A_2\) 即散块对散块,\(A_i\leftarrow B_j\) 即散块对整块,\(B_i\leftarrow B_j(i\neq j)\) 即整块对整块,\(B_i\leftarrow B_i\) 即整块自己。当然还有同块的情况。

首先带散块的都好做:我们总能拆成 \(O(\sqrt{n})\) 次查询区间 \([l,r]\) 内有多少 \([x,y]\) 中的数这样的询问(下面记这样的查询为查询 \(c(l,r,x,y)\)),离线下来值域分块平衡复杂度即可。

这部分的时间复杂度为 \(O(qB+n\sqrt{n})\)。

如果想要空间线性,发现 \(A_1\leftarrow B,A_1\leftarrow A_2\) 这样的都可以直接在端点处挂一个区间。

但 \(A_1\leftarrow A_1\) 怎么算呢,我们可以把他当作同块,用同块的方法计算。这个我们最后说。

对于整块的情况,首先考虑 \(B_i\leftarrow B_i\),发现由于一块内只有 \(O(B)\) 个数,我们预处理 \(\text{ans}(x,y)\) 表示如果询问的 \(u,d\) 在块内排名分别是 \(x,y\) 的答案即可。这部分复杂度为 \(O(nB+\frac{qn}{B})\)。为了找排名还需要处理 \(\text{rank}(i,j)\) 表示 \(i\) 这个数在 \(j\) 块中的排名,这部分也是 \(O(nB)\)。

然后再考虑 \(B_i\leftarrow B_j\)。考虑差分成值域 \([1,d]-[1,u-1]-[1,u-1]\times [u,d]\),发现最后一种是好算的:只需要查询 \([l,r]\) 这些中值在 \([x,y]\) 中的元素个数 \((1\le l,r\le \frac{n}{B})\)。

考虑 \([1,u-1]\times [u,d]\) 怎么算,写一下式子,设 \(L,R\) 为这些整块的左右边界,\(g(l,r,x,y)\) 表示 \(l\cdots r\) 这些中值在 \([x,y]\) 中的元素个数,那么这部分就是

\[\begin{aligned} &\sum_{i=L}^Rg(L,i-1,1,u-1)\times g(i,i,u,d)\\ =&\sum_{i=L}^Rg(1,i-1,1,u-1)\times g(i,i,u,d)-g(1,L-1,1,u-1)\times g(i,i,u,d)\\ =&-g(1,L-1,1,u-1)\times (g(1,R,u,d)-g(1,L-1,u,d))\\+&\sum_{i=L}^Rg(1,i-1,1,u-1)\times g(i,i,u,d) \end{aligned} \]

那这样就很容易做到线性空间了。

如果想要空间线性,只需要对每块单独做。

那还需要查询一些块的 \([1,d]\) 的贡献。考虑从小到大加入每个数,并维护 \(s_{i,j}\) 表示 \([i,j-1]\) 中的对第 \(j\) 块的答案贡献,那么如果在 \(x\) 这个块内插入了一个数,只会把 \(s_{i,x}\leftarrow s_{i,x}+\text{cnt}(i,x-1)\),其中 \(\text{cnt}(l,r)\) 表示当前 \([l,r]\) 这些块内已经插入了多少个数。\(\text{cnt}\) 可以用前缀和维护。

\([l,r]\) 块的答案就是 \(\sum_{i=l}^rs_{l,i}\)。那这部分复杂度是 \(O(\frac{n^2}{B})\),且空间复杂度天然是线性。

对于同块的情况,朴素的想法是直接拆成 \(O(\sqrt{n})\) 次查询 \(c(l,r,x,y)\),但是空间不好卡。考虑再分一次块,把这个散块分成长度为 \(S\) 的块,每块内直接暴力 \(O(S^2)\) 算,块之间就直接加询问,那么这部分的时间复杂度是 \(O(\frac{qB}{S}+qBS)\)。注意由于暴力的那些块长加起来是 \(B\),因此暴力的复杂度是 \(O(BS)\) 而非 \(O(BS^2)\)。

如果只看时间,我们应当取 \(S=1\);但空间复杂度其实是 \(O(\frac{qB}{S})\),我们可以偷偷调整 \(B\) 和 \(S\) 的值(不是)并假装他是线性。

取 \(B=O(\sqrt{n})\),那么总的复杂度是 \(O((n+q)\sqrt{n})\),空间是(迫真)线性的,可以通过 P6579

//-DYUNQIAN -std=c++14 -O2 -Wall
#include<bits/stdc++.h>

#define ll long long

using namespace std;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;(c<'0'||c>'9');c=getchar()){if(c=='-')f=-1;}
	for(;(c>='0'&&c<='9');c=getchar())x=x*10+(c&15);
	return x*f;
}

mt19937 rnd(time(0));
int randint(int l,int r){return rnd()%(r-l+1)+l;}

void Assert(bool c,int L=0){if(!c){cout<<"Assertion Failed at "<<L<<endl;exit(0);}}

const int N=1e5+5;
const int M=2e5+5;
const int B=500;
const int NB=500;

int n,m;
namespace ds{// O(sqrtn) add O(1) sum
	int sumb[B+5],sum[N],st[NB+5],ed[NB+5],bl[N];
	void build(int siz){
		memset(st,63,sizeof(st));
		for(int i=1;i<=n;i++)bl[i]=(i-1)/siz+1,ed[bl[i]]=i,st[bl[i]]=min(st[bl[i]],i);
	}
	void add(int x){
		for(int i=x;i<=ed[bl[x]];i++)sum[i]++;
		for(int i=bl[x];i<=bl[n];i++)sumb[i]++;
	}
	int qsum(int l,int r){
		if(l>r)return 0;
		int ql=bl[l],qr=bl[r];
		if(ql==qr)return sum[r]-(l==st[ql]?0:sum[l-1]);
		int ans=sumb[qr-1]-sumb[ql];
		ans+=sum[r],ans+=sum[ed[ql]]-(l==st[ql]?0:sum[l-1]);
		return ans;
	}
};

int st[NB+5],ed[NB+5],bl[N],S,Sq,a[N];
struct Q{
	int l,r,vl,vr,f,id,typ;// type = 1 : [a[i],n] & [vl,vr] | type = 2 : [1,a[i]] & [vl,vr]
	Q(int L=0,int R=0,int VL=0,int VR=0,int F=0,int ID=0,int Ty=0):l(L),r(R),vl(VL),vr(VR),f(F),id(ID),typ(Ty){}
};
vector<Q>qs[N];

ll ans[M];
void addq(int l,int r,int u,int d,int ql,int qr,int id,int typ){
	if(l>r||ql>qr)return ;
	// type = 1 : sum{i = l...r}sum{j = ql...qr} u <= a[i] < a[j] <= d  ( l<=r<=ql<=qr )
	// type = 2 : sum{i = l...r}sum{j = ql...qr} u <= a[j] < a[i] <= d  ( ql<=qr<=l<=r )
	if(typ==1)Assert(l<=r&&r<=ql&&ql<=qr);
	if(typ==2)Assert(ql<=qr&&qr<=l&&l<=r);
	qs[qr].emplace_back(Q(l,r,u,d,1,id,typ));
	qs[ql-1].emplace_back(Q(l,r,u,d,-1,id,typ));
}
void solveA(int l,int r,int u,int d,int id){
	if(l>r)return ;
	int qr=min(l+Sq-1,r);
	for(int i=l;i<=qr;i++)if(u<=a[i]&&a[i]<=d)for(int j=i+1;j<=qr;j++)if(a[i]<=a[j]&&a[j]<=d)ans[id]++;
	addq(l,qr,u,d,qr+1,r,id,1),solveA(qr+1,r,u,d,id);
}

int pr[N],sf[N],res[B+5][B+5];
struct qry{int l,r,u,d;}ques[M];

vector<int>lsh;
int b[N],cur[N],num[N],mul[M];
void solveB(int l,int r){
	lsh.clear();int V=r-l+1;lsh.resize(V+2);int c=bl[l];
	for(int i=l;i<=r;i++)lsh[i-l]=a[i];lsh[V]=0,lsh[V+1]=n+1;
	sort(lsh.begin(),lsh.end());
	for(int i=1;i<=V+1;i++){
		for(int j=lsh[i-1]+1;j<=lsh[i];j++)sf[j]=i;
		for(int j=lsh[i-1];j<lsh[i];j++)pr[j]=i-1;
	}
	for(int i=l;i<=r;i++)b[i]=lower_bound(lsh.begin(),lsh.end(),a[i])-lsh.begin();
	for(int i=l;i<=r;i++){
		for(int j=i+1;j<=r;j++)if(b[i]<b[j])res[b[i]][b[j]]++;
	}
	for(int i=V;i>=1;i--)for(int j=i;j<=V;j++)res[i][j]+=res[i+1][j]+res[i][j-1]-res[i+1][j-1];
	
	for(int i=l;i<=r;i++)cur[a[i]]++;
	for(int i=1;i<=n;i++)cur[i]+=cur[i-1];
	
	for(int i=1;i<=m;i++){
		auto t=ques[i];int ql=bl[t.l],qr=bl[t.r];
		if(ql==qr)continue;
		if(ql<c&&c<qr)ans[i]+=res[sf[t.u]][pr[t.d]];
		if(ql<c&&c<qr)ans[i]-=1ll*(cur[t.d]-cur[t.u-1])*num[t.u-1];
		if(c==ql+1&&ql<qr-1)mul[i]=num[t.u-1],ans[i]-=1ll*(num[t.d]-num[t.u-1])*num[t.u-1];
		if(c==qr&&ql<qr-1)ans[i]+=1ll*(num[t.d]-num[t.u-1])*mul[i];
	}
	
	for(int i=1;i<=n;i++)num[i]+=cur[i],cur[i]=0;
	for(int i=1;i<=V;i++)for(int j=1;j<=V;j++)res[i][j]=0;
}

int con[NB+5][NB+5],cnt[NB+5],pos[N];

struct Qs{
	int l,r,f,id;
	Qs(int L=0,int R=0,int F=0,int ID=0):l(L),r(R),f(F),id(ID){}
};
vector<Qs>vec[N];
void solve(int l,int r,int u,int d,int id){
	int ql=bl[l],qr=bl[r];
	if(ql==qr){solveA(l,r,u,d,id);return ;}
	solveA(l,ed[ql],u,d,id),solveA(st[qr],r,u,d,id);
	vec[d].emplace_back(Qs(ql+1,qr-1,1,id));
	vec[u-1].emplace_back(Qs(ql+1,qr-1,-1,id));
	addq(l,ed[ql],u,d,ed[ql]+1,r,id,1),addq(st[qr],r,u,d,ed[ql]+1,st[qr]-1,id,2);
}

signed main(void){

#ifdef YUNQIAN
	freopen("tears.in","r",stdin);
	freopen("tears.out","w",stdout);
#endif

	n=read(),m=read();
	S=200,Sq=35;
	for(int i=1;i<=n;i++)a[i]=read();memset(st,63,sizeof(st));
	for(int i=1;i<=n;i++)bl[i]=(i-1)/S+1,st[bl[i]]=min(st[bl[i]],i),ed[bl[i]]=i;
	for(int i=1;i<=m;i++){
		int l=read(),r=read(),u=read(),d=read();
		ques[i].l=l,ques[i].r=r,ques[i].u=u,ques[i].d=d;
		solve(l,r,u,d,i);
	}
	
	for(int i=1;i<=n;i+=S)solveB(i,min(i+S-1,n));
	
	ds::build(300);
	for(int i=1;i<=n;i++){
		ds::add(a[i]);
		for(auto t:qs[i]){
			for(int j=t.l;j<=t.r;j++){
				int ql=t.vl,qr=t.vr;
				if(a[j]<ql||a[j]>qr)continue;
				if(t.typ==1)ql=max(ql,a[j]);
				if(t.typ==2)qr=min(qr,a[j]);
				if(t.f==1)ans[t.id]+=ds::qsum(ql,qr);
				else ans[t.id]-=ds::qsum(ql,qr);
			}
		}
	}
	
	for(int i=1;i<=n;i++)pos[a[i]]=i;
	for(int i=1;i<=n;i++){
		int p=pos[i],bp=bl[p];
		for(int j=1;j<bp;j++)con[j][bp]+=cnt[bp-1]-cnt[j-1];
		for(int j=bp;j<=bl[n];j++)cnt[j]++;
		for(auto t:vec[i]){
			for(int j=t.l+1;j<=t.r;j++){
				if(t.f==1)ans[t.id]+=con[t.l][j];
				else ans[t.id]-=con[t.l][j];
			}
		}
	}
	
	for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';

	return 0;
}

标签:时代,leftarrow,int,sum,id,NOI2020,qr,眼泪,ql
From: https://www.cnblogs.com/YunQianQwQ/p/17502600.html

相关文章

  • 免费ChatGPT网站:解锁无限创造力与智慧对话的新时代
    在当今快速发展的科技领域,人工智能(AI)正以惊人的速度改变着我们的生活。其中,自然语言处理(NLP)技术的突破引发了全球范围内的关注和讨论。作为前沿的NLP应用之一,ChatGPT已经成为了解决问题、提供信息以及增强创造力的重要工具。ChatGPT-掌握智能对话的钥匙如果你渴望与一个真实、智......
  • 免费ChatGPT网站:解锁无限创造力与智慧对话的新时代
    在当今快速发展的科技领域,人工智能(AI)正以惊人的速度改变着我们的生活。其中,自然语言处理(NLP)技术的突破引发了全球范围内的关注和讨论。作为前沿的NLP应用之一,ChatGPT已经成为了解决问题、提供信息以及增强创造力的重要工具。ChatGPT-掌握智能对话的钥匙如果你渴望与一个真实、智......
  • 浪潮信息张东:多元算力时代,整机软硬协同是发展操作系统的关键
    随着全球数字化转型的加速,数字经济成为经济增长的主引擎,以5G、智算中心为代表的新兴基础设施的不断建设,持续推动着中国服务器及服务器操作系统的发展。经过数十年的探索,中国的服务器操作系统产业新的格局逐渐成型,以龙蜥为代表的三大主流开源Linux社区为根源,大量国内服务器操作系统......
  • 趋势分享 | 多云时代数据安全面临的挑战
    IT 和数据管理研究和咨询公司EMA(Enterprise Management Associates)早前发布的一份《多云环境下的数据安全》(Data Security in a Multi-Cloud World)研究报告,调查了来自十个以上不同行业垂直领域、公司规模在 500 人以上的 204 名受访人员。调查结果发现,数据安全保护已......
  • 数字时代,你想成为一只“弱鸡”,还是一个“超级个体”?
       电话延伸了人类的耳朵,屏幕延伸了人类的眼睛,汽车这样的交通工具延伸了人类的腿脚,人类的生存能力开始变得和技术相关,而这个趋势仍在加剧。    如今,Web3延伸了人的综合体验,AI延伸了人类的大脑,它们正以摧枯拉朽的态势,拉开人与人之间的差距。数字时代,你想成为一只弱鸡,还是一个......
  • 华为云邓明昆:云原生时代,以开源赋能数字化转型
    摘要:云原生技术以“极致弹性、分布式、松耦合、高韧性”等特征,可有效帮助企业实现基础架构升级,业务快速创新。近日,以“开源赋能,普惠未来”为主题的开放原子全球开源峰会在北京亦创国际会展中心顺利举行。其中,由华为云承办的以“探索云原生技术发展与应用实践,赋能企业数字化转型”......
  • 华为云邓明昆:云原生时代,以开源赋能数字化转型
    2023年6月11日-13日,以“开源赋能,普惠未来”为主题的开放原子全球开源峰会在北京亦创国际会展中心顺利举行。其中,由华为云承办的以“探索云原生技术发展与应用实践,赋能企业数字化转型”为主题的2023开放原子全球开源峰会--云原生分论坛于6月13日圆满落幕。此次云原生分论坛邀请开发......
  • 从知识到想法:数字时代的深度学习与知识管理
    一、树形结构:激发想法的准秩序空间在探索知识与想法的独特联系时,我们发现了一种重要的工具:树形结构。但是,其真正的价值并不仅仅在于其可视化的特性,而是其作为一种准秩序化的信息空间的能力。在这个空间中,知识和想法的关系以一种既有秩序又保持混沌的方式表现出来,为我们激发新的想......
  • 深度链接,深度思考——数字时代的笔记方法
    本文探讨了深度链接在知识管理和理解上的重要性。深度链接不仅允许我们直接回到原始的上下文进行重新思考,还可以在不同内容层次间灵活跳转和关联,从而更深入全面地理解一个主题。​文章首先对深度链接与转述进行了对比,指出虽然转述能够帮助我们用自己的话来理解和消化信息,但在处理......
  • 服务器告别“独奏”时代 联想奏响“交响乐”
    作者|曾响铃文|响铃说1964年,IBM发布了第一台真正意义上的服务器。从此以后,服务器的发展与信息化、数字化、智能化的一波波浪潮同步,开启了超过半个世纪的悠久历程,见证时代的一次次巨变。巨资砸技术创新,大力拓展生态,狂热布局营销渠道,与供应链反复博弈想要获取优势地位,内部深度管......