D. Pair of Numbers (ST表&二分&双指针)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Pair of Numbers (ST表&二分&双指针)相关的知识,希望对你有一定的参考价值。

D. Pair of Numbers (ST表&二分&双指针)

显然就是找最大区间 g c d = m i n gcd=min gcd=min​ ,且长度具有二分性,然后没了,代码懒得写,参考的题解区。

#include <stdio.h>
inline int read()
{
	int num=0;char c=getchar();
	while(c<48||c>57)c=getchar();
	while(c>47&&c<58)num=num*10+(c^48),c=getchar();
	return num;
}
inline int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}
inline int lcm(int a,int b)
{
	return a>b?b:a;
}
int st[300005][23],log2[300005],mn[300005][23];
inline int queryG(int a,int b)
{
	int k=log2[b-a+1]-1;
	return gcd(st[a][k],st[b-(1<<k)+1][k]);
}
inline int queryL(int a,int b)
{
	int k=log2[b-a+1]-1;
	return lcm(mn[a][k],mn[b-(1<<k)+1][k]);
}
int ans,qaqaqaq[300005];
inline int qaq(int qwq,int n)
{
	int a=0;
	for(int i=1;i+qwq<=n;i++)
	{
		if(queryG(i,i+qwq)==queryL(i,i+qwq))qaqaqaq[a++]=i;
	}
	if(a)return ans=a;
	else return 0;
}
int main()
{
	int n=read();
	for(int i=1;i<=n;i++)st[i][0]=mn[i][0]=read(),log2[i]=log2[i>>1]+1;
	for(int i=1;i<=22;i++)
		for(int j=1;j+(1<<i)-1<=n;j++)st[j][i]=gcd(st[j][i-1],st[j+(1<<i-1)][i-1]),mn[j][i]=lcm(mn[j][i-1],mn[j+(1<<i-1)][i-1]);
	int l=0,r=n-1,qwq=114514;
	while(l<=r)
	{
		int m=l+(r-l>>1);
		if(qaq(m,n))l=m+1,qwq=m;
		else r=m-1;
//		printf("D %d %d\\n",l,r);
	}
	printf("%d %d\\n",ans,qwq);
	for(int i=0;i<ans;i++)printf("%d ",qaqaqaq[i]);
	return 0;
}

这里主要讲下类似双指针的做法。

我们可以枚举那个最小值 a i a_i ai,然后两个指针 l , r l,r l,r 往两边走,每次取最大值。

然后 i i i 移动到 r + 1 r+1 r+1 ,这样总复杂度最多 O ( 2 n ) O(2n) O(2n)

为什么呢?

考虑如上图 a i a_i ai​ 的最大范围是 [ L , R ] [L,R] [L,R]​ ,对于点 A A A​ ,能整除 A A A​ 的点,必然能整除 a i a_i ai​ ,所以 A A A​的右端点 R A R_A RA​ 不会超过 R R R​ ,但是左端点最多是 i + 1 i+1 i+1​ 。

所以显然长度更劣,不会对答案有贡献, A A A a i a_i ai​ 左端点同理。

因此 i i i 可以跳到 R + 1 R+1 R+1

// Problem: D. Pair of Numbers
// Contest: Codeforces - Codeforces Round #209 (Div. 2)
// URL: https://codeforces.ml/contest/359/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-08-04 16:23:27
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=3e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int a[N],b[N],ans,cnt;
int main(){
	int n;scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1,l,r;i<=n;){
		l=r=i;
		while(l-1>0&&a[l-1]%a[i]==0) l--;
		while(r+1<=n&&a[r+1]%a[i]==0) r++;
		i=r+1;
		r-=l;
		if(r>ans) ans=r,cnt=0;
		if(r==ans) b[++cnt]=l;
	}
	printf("%d %d\\n",cnt,ans);
	for(int i=1;i<=cnt;i++) printf("%d ",b[i]);printf("\\n");
	return 0;
}

以上是关于D. Pair of Numbers (ST表&二分&双指针)的主要内容,如果未能解决你的问题,请参考以下文章

D. Pair of Topics1400 / 思维 二分

Eming cup Problem D. Game of numbers

Codeforces Round #627 (Div. 3) D. Pair of Topics(二分/直接遍历)

D. Arpa and a list of numbers Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017)(示

Educational Codeforces Round 41 D. Pair Of Lines

D. Yet Another Yet Another Task (ST表模版 + 单调队列)