首页 > 其他分享 >P9032 [COCI2022-2023#1] Neboderi 题解

P9032 [COCI2022-2023#1] Neboderi 题解

时间:2023-12-27 10:12:12浏览次数:40  
标签:COCI2022 P9032 return gcd int 题解 mid gc log

P9032

考试题。

发现 \(g\) 的值是若干个相同的段,且段数很少,因为每次取 \(\gcd\) 至少会将值域变为原来的一半。所以段数是 \(\mathcal{O}(\log V)\) 的。

然后就可以从小到大枚举左端点,然后枚举 \(g\) 的值,找的是最远的满足 \(\gcd(a_l,\dots,a_r)=g\) 的 \(r\),这里可以使用二分。二分的 check 使用 ST 表即可做到 \(\mathcal{O}(n\log n\log^2V)\)。\(k\) 的话再判断一下就行。常数极小,可以通过。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
int a[1000010],gc[22][1000010];
ll s[1000010];
int gcd(int a,int b){
	while(b)swap(a%=b,b);
	return a;
}
int ask(int l,int r){
	int d=__lg(r-l+1);
	return gcd(gc[d][l],gc[d][r-(1<<d)+1]);
}
int work(int st,int lim,int g){
	int l=lim,r=n,res=lim;
	while(l<=r){
		int mid=(l+r)>>1;
		if(ask(st,mid)==g)l=mid+1,res=mid;
		else r=mid-1;
	}
	return res;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),gc[0][i]=a[i],s[i]=s[i-1]+a[i];
	for(int i=1;i<=__lg(n);i++)for(int j=1;j+(1<<i)-1<=n;j++)gc[i][j]=gcd(gc[i-1][j],gc[i-1][j+(1<<i-1)]);
	ll ans=a[n];
	for(int i=1;i<=n-m+1;i++){
		int x=i+m-1;ans=max(ans,ask(i,i+m-1)*1ll*(s[i+m-1]-s[i-1]));
		while(x<n){
			int g=ask(i,x+1);
			int p=work(i,x+1,g);
			if(p-i+1>=m)ans=max(ans,(s[p]-s[i-1])*g);
			x=p;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

但是这个东西显然不是正解。正难则反,发现 \(i\) 的右端点容易由 \(i+1\) 得到。故可以从大到小的枚举 \(i\)。然后用一个数据结构(比如链表)存下当前 \(\log V\) 个 \(\gcd\) 的位置。将这些 \(\gcd\) 都和 \(h_i\) 做一遍即可。然后相同的取较大的即可。

标签:COCI2022,P9032,return,gcd,int,题解,mid,gc,log
From: https://www.cnblogs.com/Pengzt/p/17929892.html

相关文章

  • [CTSC2018]暴力写挂题解
    我们先将柿子变成\(\frac{1}{2}(dis_{x,y}+dep_{x}+dep_{y})-dep'_{lca'}\)考虑边分治,枚举断边,我们将一个点在第二棵树上的点权看成是\(v_x=d_x+dep_x\),答案就为\(v_x+v_y+dep'_{lca'}\)对于每次边分治将分治联通块内所有点在第二棵树上的建出虚树,同时将分治联通块以分治中心......
  • CF1887D Split 题解
    Problem-D-CodeforcesSplit-洛谷我现在水平好烂,再做下去自信心就全败没了先考虑\(Q=1\)怎么做?两种做法:暴力枚举分界点,左右判断暴力枚举\(\max\limits_{i=l}^{x}a_i\),找到最靠右边的分界点位置\(x\),判断是否\(\max\limits_{i=l}^{x}a_i<\min\limits......
  • [ABC267F] Exactly K Steps 题解
    [ABC267F]ExactlyKSteps题解思路首先发现,如果对于查询\((u,k),k>0\)可行,那么对于\((u,k-1)\)也一定可行,因为往回走一步就可以了,所以对于一个点可以找到离它最远的点,根据直径的结论,这个点一定是直径的端点之一。为了方便做,以直径的端点之一为根,然后写一个K级祖......
  • 【CF30E】Tricky and Clever Password 题解(manacher + exKMP)
    manacher+exKMP+二分。感觉是最粗暴的方法,想出来之后自己硬莽了4k,荣获题解区最长。Solution约定:下文所提及到的所有的回文串,均指奇长度回文串。显然把题目拆成两个部分,中间的回文串,以及两边相同的连续子串。考虑一下从哪个入手比较好。忘记是咋想的了,易得从两边相同......
  • [SNOI2019] 网络 题解
    [SNOI2019]网络题解最喜欢这道题。简要题意给一颗\(n\)个节点的树和一个参数\(d\),定义两个节点\(x,y\)之间的距离为\(x\)到\(y\)的简单路径上的边数。定义一个树上连通块的权值为连通块中任意两点的距离之和。定义一个树上连通块的直径为连通块中任意两点距离的最......
  • CF1887C Minimum Array 题解
    Problem-1887C-CodeforcesMinimumArray-洛谷有点被降智了/ll首先区间修改显然先转化成差分序列单点修改。显然对于相同的操作序列,\(a_i\)的取值对答案无影响,因此我们可以先让\(a_i\)全部取\(0\),最后再加回来即可假如说操作到某一时刻,\(a_i\)的值中第一个......
  • 洛谷B3647 【模板】Floyd 题解 floyd算法 求 多源多汇最短路
    题目链接:https://www.luogu.com.cn/problem/B3647floyd算法:https://oi-wiki.org/graph/shortest-path/#floyd-算法示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=101;intn,m,f[maxn][maxn];intmain(){scanf("%d%d",&n......
  • [题解]CF1811D Umka and a Long Flight
    思路假设原题目中的\(n\)在本文中为\(num\),则原长方形的长\(m=f_{num+1}\)和宽\(n=f_{num}\)。显然对于最初始的长方形,显然是要将一个\(f_{num}\timesf_{num}\)的长方形丢进去的,并且要么放最左边,要么放在最右边。因为对于当前的\(m=f_{num+1}=f_{num}+......
  • CF768G The Winds of Winter题解
    我们考虑暴力咋做,每次得到一个森林之后,必定是从最大的树上摘一棵子树,挪到最小的树上,所以此时的答案为\(max(siz_{mx}-x,siz_{mn}+x,siz_{次大值})\),于是发现\(x=\frac{siz_{mx}-siz_{mn}}{2}\)时答案最优,所以只需找到这个值的前驱后继即可我们使用\(\text{multiset}\)实现,......
  • HNOI2017影魔题解
    HNOI2017影魔对于两种贡献,都只用考虑左边第一个比自己大的,和右边第一个比自己大的数,分别记为\(l_i、r_i\)对于询问一,每个数对\((l_i,r_i)\)构成全部情况对于询问二,可以拆分成\(x=l_i\)时,\(y\in[i+1,r_i-1]\),以及\(y=r_i\)时,\(x\in[l_i+1,i-1]\)我们考虑用扫描线......