• Gym102354B Yet Another Convolution


    Yet Another Convolution

    You are given an integer array (a_1, dots, a_n) and an integer array (b_1, dots, b_n).

    You have to calculate the array (c_1, dots, c_{n}) defined as follows:

    [c_k = maxlimits_{gcd(i,j) = k} |a_i - b_j| ext{.} ]

    (1 leq n leq 10^5)

    题解

    根据调和级数,我们只需要处理 (c_1)

    考虑分别计算每个 (a_i) 对应的 (b_j) 的最大和最小值。显然这两个问题是对称的。

    考虑最大值,整体二分。我们需要判断每个 (a_i) 有没有一个对应的 (b_jin [l,r])

    考虑莫比乌斯反演,(sum_{d|i,d|j}mu(d)),那么开个cnt数组

    对于每个j, for d|j, cnt[d]+=mu[d]
    对于每个i, for d|i, sum+=cnt[d]
    

    如果sum>0就说明存在对应的 (b_j)

    时间复杂度 (O(n ln n log v))

    CO int N=1e5+10,inf=1e9;
    int pri[N],tot,mu[N];
    vector<int> divi[N];
    int a[N],b[N],c[N];
    
    namespace Task{
    	int n,ans;
    	pair<int,int> a[N],b[N];
    	pair<int,int> ta[N],tb[N];
    	int cnt[N];
    	
    	void solve_min(int la,int ra,int lb,int rb,int lv,int rv){
    		if(la>ra or lb>rb) return;
    		if(lv==rv){
    			for(int i=la;i<=ra;++i) ans=max(ans,a[i].first-lv);
    			return;
    		}
    		int mv=(lv+rv)>>1;
    		int ql=lb,qr=rb;
    		for(int i=lb;i<=rb;++i){
    			if(b[i].first<=mv){
    				for(int d:divi[b[i].second]) cnt[d]+=mu[d];
    				tb[ql++]=b[i];
    			}
    			else tb[qr--]=b[i];
    		}
    		int mb=ql-1;
    		ql=la,qr=ra;
    		for(int i=la;i<=ra;++i){
    			int sum=0;
    			for(int d:divi[a[i].second]) sum+=cnt[d];
    			if(sum) ta[ql++]=a[i];
    			else ta[qr--]=a[i];
    		}
    		int ma=ql-1;
    		for(int i=lb;i<=rb;++i)if(b[i].first<=mv)
    			for(int d:divi[b[i].second]) cnt[d]-=mu[d];
    		copy(ta+la,ta+ra+1,a+la);
    		copy(tb+lb,tb+rb+1,b+lb);
    		solve_min(la,ma,lb,mb,1,mv);
    		solve_min(ma+1,ra,mb+1,rb,mv+1,rv);
    	}
    	void solve_max(int la,int ra,int lb,int rb,int lv,int rv){
    		if(la>ra or lb>rb) return;
    		if(lv==rv){
    			for(int i=la;i<=ra;++i) ans=max(ans,rv-a[i].first);
    			return;
    		}
    		int mv=(lv+rv+1)>>1;
    		int ql=lb,qr=rb;
    		for(int i=lb;i<=rb;++i){
    			if(b[i].first>=mv){
    				for(int d:divi[b[i].second]) cnt[d]+=mu[d];
    				tb[qr--]=b[i];
    			}
    			else tb[ql++]=b[i];
    		}
    		int mb=qr+1;
    		ql=la,qr=ra;
    		for(int i=la;i<=ra;++i){
    			int sum=0;
    			for(int d:divi[a[i].second]) sum+=cnt[d];
    			if(sum) ta[qr--]=a[i];
    			else ta[ql++]=a[i];
    		}
    		int ma=qr+1;
    		for(int i=lb;i<=rb;++i)if(b[i].first>=mv)
    			for(int d:divi[b[i].second]) cnt[d]-=mu[d];
    		copy(ta+la,ta+ra+1,a+la);
    		copy(tb+lb,tb+rb+1,b+lb);
    		solve_max(ma,ra,mb,rb,mv,rv);
    		solve_max(la,ma-1,lb,mb-1,lv,mv-1);
    	}
    	int main(){
    		ans=0;
    		solve_min(1,n,1,n,1,inf);
    		solve_max(1,n,1,n,1,inf);
    		return ans;
    	}
    }
    
    int main(){
    	int n=read<int>();
    	mu[1]=1;
    	for(int i=2;i<=n;++i){
    		if(!pri[i]) pri[++tot]=i,mu[i]=-1;
    		for(int j=1;j<=tot and i*pri[j]<=n;++j){ // edit 1: ++j
    			pri[i*pri[j]]=1;
    			if(i%pri[j]==0){
    				mu[i*pri[j]]=0;
    				break;
    			}
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n/i;++j) divi[j*i].push_back(i);
    	for(int i=1;i<=n;++i) read(a[i]);
    	for(int i=1;i<=n;++i) read(b[i]);
    	for(int i=1;i<=n;++i){
    		Task::n=n/i;
    		for(int j=1;j<=Task::n;++j) Task::a[j]={a[j*i],j};
    		for(int j=1;j<=Task::n;++j) Task::b[j]={b[j*i],j};
    		c[i]=Task::main();
    	}
    	for(int i=1;i<=n;++i) printf("%d%c",c[i]," 
    "[i==n]);
    	return 0;
    }
    
  • 相关阅读:
    牛客小白月赛21
    牛客小白月赛21
    CodeForces 1333-C Eugene and an array(子区间和为0、前缀和)
    页面大小、页表项、虚拟地址和物理地址之间的关系(转)
    001-Paint_FreePythonGames项目代码详解(每行都有注释!!!)
    第17讲~第19讲:函数:python的乐高积木
    第16讲:序列!序列!
    第15讲:字符串格式化
    练习23--字符串、字节和编码
    第14讲:字符串--各种奇葩内置方法
  • 原文地址:https://www.cnblogs.com/autoint/p/12298870.html
Copyright © 2020-2023  润新知