ICode9

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

题解-[SDOI/SXOI2022]整数序列

2022-05-31 08:33:52  阅读:125  来源: 互联网

标签:ch SDOI SXOI2022 ++ 题解 else int maxn vec


数据范围很诈骗,但poly log做法思考无果还是指引我们来想sqrt做法。

首先有一个很暴力的 \(O(cnt_x+cnt_y)\) 的做法。看到和出现次数有关则可以想根号分治。我们设定一个阈值 \(B\),对于两者都 \(<B\) 的部分可以暴力做,都大于 \(B\) 的部分也可以暴力做,因为这样的最多只会有 \(N^2/B\) 次计算。

然后思考一大一小,容易发现两者顺序无关,不妨设 \(cnt_x>cnt_y\)。

那么容易想到 \(x\) 中有很多是不必要的部分。实际上只有 \(y\) 中每个极长元素段在 \(x\) 中的相同长度的前驱和后继才是必要的。然而还有一个问题就是这样不合法的情况有可能变合法,那么我们不妨再放入一段前驱的前驱段。这样就把 \(x\) 的长度变得和 \(y\) 同阶了。

总的预处理复杂度变为 \(O(\frac{n^2}{B})\),总复杂度 \(O(\frac{n^2}{B}+qB)\),取 \(B=\frac{n}{\sqrt{q}}\) 即可得到 \(O(n\sqrt{q})\)。

实现细节可以考虑离线询问,然后预处理前驱后继,全部归并排序后再去重。

#include<bits/stdc++.h>
#define pb push_back
#define pii pair<int,int>
#define MP make_pair
#define F first
#define S second
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
const ll inf=0x3f3f3f3f3f3f3f3f;
template<typename T>
void read(T &x){
	T sgn=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())if(ch=='-')sgn=-1;
	for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
	x*=sgn;
}
int n,m,a[maxn],b[maxn],num;
int B,pre[maxn],nxt[maxn],len;
int d[maxn],e[maxn],f[maxn],g[maxn];
vector<int>vec[maxn];
vector<pii>qry[maxn];
ll s1[maxn],s2[maxn],mp[maxn];
pii c[maxn];
bool vis[maxn],mark[maxn],zz[maxn];
map<pii,ll> ans;
ll Ans[maxn];
ll BF(){
	ll now=-inf;
	vis[n]=1;mp[n]=0;
	for(int k=1;k<=len;k++){
		s1[k]=s1[k-1]+b[c[k].S];
		s2[k]=s2[k-1]+c[k].F;
		if(vis[s2[k]+n])now=max(now,s1[k]-mp[s2[k]+n]);
		if(!vis[s2[k]+n])mp[s2[k]+n]=s1[k],vis[s2[k]+n]=1;
		else mp[s2[k]+n]=min(mp[s2[k]+n],s1[k]);
	}
	vis[n]=0;
	for(int k=1;k<=len;k++)vis[s2[k]+n]=0;
	return now;
}
int main(){
//	freopen("sequence.in","r",stdin);
//	freopen("sequence.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<=n;i++)read(a[i]),vec[a[i]].pb(i);
	for(int i=1;i<=n;i++)if(vec[i].size())num++;
	for(int i=1;i<=n;i++)read(b[i]);
	B=n/sqrt(m)+1;
	for(int i=1;i<=m;i++){
		int x,y;
		read(x);read(y);
		if(ans.find(MP(x,y))!=ans.end()){Ans[i]=ans[MP(x,y)];continue;};
		if(((int)vec[x].size()<B&&(int)vec[y].size()<B)||((int)vec[x].size()>=B&&(int)vec[y].size()>=B)){
			len=0;
			for(int p=0,q=0;p<(int)vec[x].size()||q<(int)vec[y].size();){
				if(p>=(int)vec[x].size())c[++len]=MP(-1,vec[y][q++]);
				else if(q>=(int)vec[y].size())c[++len]=MP(1,vec[x][p++]);
				else{
					if(vec[x][p]<vec[y][q])c[++len]=MP(1,vec[x][p++]);
					else c[++len]=MP(-1,vec[y][q++]);
				}
			}
			Ans[i]=ans[MP(x,y)]=ans[MP(y,x)]=BF();
		}else{
			if(vec[x].size()<vec[y].size())swap(x,y);
			qry[x].pb(MP(y,i));
		}
	}
	for(int i=1;i<=n;i++)if(qry[i].size()){
		for(int j:vec[i])mark[j]=1;
		for(int j=1;j<=n;j++){
			pre[j]=pre[j-1];
			if(mark[j-1])pre[j]=j-1;
		}
		nxt[n+1]=n+1;
		for(int j=n;j;j--){
			nxt[j]=nxt[j+1];
			if(mark[j+1])nxt[j]=j+1;
		}
		for(pii o:qry[i]){
			int j=o.F;
			if(ans.find(MP(i,j))!=ans.end()){
				Ans[o.S]=ans[MP(i,j)];
				continue;
			}
			len=0;
			int u=0,v=0,w=0,tmp=0;
			for(int k:vec[j]){
				if(nxt[k]<=n){
					if(nxt[k]>tmp)d[++u]=tmp=nxt[k];
					else if(nxt[tmp]<=n)d[++u]=tmp=nxt[tmp];
				}
			}
			tmp=n+1;
			for(int l=(int)vec[j].size()-1;~l;l--){
				int k=vec[j][l];
				if(pre[k]){
					if(pre[k]<tmp)e[++v]=tmp=pre[k];
					else if(pre[tmp])e[++v]=tmp=pre[tmp];
					if(pre[tmp])e[++v]=tmp=pre[tmp];
				}
			}
			reverse(e+1,e+1+v);
			for(int p=1,q=1;p<=u||q<=v;){
				if(p>u)f[++w]=e[q++];
				else if(q>v)f[++w]=d[p++];
				else{
					if(d[p]<e[q])f[++w]=d[p++];
					else f[++w]=e[q++];
				}
			}
			for(int p=1,q=0;p<=w||q<(int)vec[j].size();){
				if(p>w)g[++len]=vec[j][q++];
				else if(q>=(int)vec[j].size())g[++len]=f[p++];
				else{
					if(f[p]<vec[j][q])g[++len]=f[p++];
					else g[++len]=vec[j][q++];
				}
			}
			tmp=len;len=0;
			for(int k=1;k<=tmp;k++){
				if(g[k]!=g[len])g[++len]=g[k];
			}
			for(int k=1;k<=len;k++){
				c[k].F=a[g[k]]==i?1:-1;
				c[k].S=g[k];
			}
			Ans[o.S]=ans[MP(i,j)]=ans[MP(j,i)]=BF();
			for(int k=1;k<=len;k++)if(a[c[k].S]==i)zz[c[k].S]=0;
		}
		for(int j:vec[i])mark[j]=0;
	}
	for(int i=1;i<=m;i++)printf("%lld\n",Ans[i]);
	return 0;
}

标签:ch,SDOI,SXOI2022,++,题解,else,int,maxn,vec
来源: https://www.cnblogs.com/zcr-blog/p/16329118.html

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

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

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

ICode9版权所有