Codeforces Round #717 (Div. 2) 1516 D. Cut(区间互质+倍增思想)
发布日期:2021-06-30 10:32:28 浏览次数:2 分类:技术文章

本文共 3369 字,大约阅读时间需要 11 分钟。

分在一组的前提是,任意两个数都互质

考虑预处理一个 f [ i ] f[i] f[i]表示 [ i + 1 , f i − 1 ] [i+1,f_i-1] [i+1,fi1]的所有数和 a i a_i ai互质,且 f i f_i fi最大

这样我们就能得到 s t [ i ] st[i] st[i]表示 [ i , s t i − 1 ] [i,st_i-1] [i,sti1]能分成一组而且最长

s t [ i ] = min ⁡ j = i f i − 1 { f [ j ] } st[i]=\min\limits_{j=i}^{f_i-1}\{f[j]\} st[i]=j=iminfi1{

f[j]}

这个很好理解,虽然自己最远能到达 f i − 1 f_i-1 fi1,但是还需要考虑其他数字的限制

但是暴力枚举复杂度爆炸

考虑对 a i a_i ai来说,存在因子 x 1 , x 2 . . . x k x_1,x_2...x_k x1,x2...xk

那么只需要满足组内的数没有这些因子就好了!!!

我们从 n n n 1 1 1倒序枚举 a i a_i ai,分解质因子,并刷新每种因子出现的最早位置,记 n x t [ x ] nxt[x] nxt[x]表示质因子 x x x出现在索引 i i i后的最早位置

那么 f [ i ] = m i n ( f [ i ] , n x [ x j ] ) f[i]=min(f[i],nx[x_j]) f[i]=min(f[i],nx[xj]),其中 x j x_j xj a i a_i ai的一个因子

这样我们可以得到 f f f数组,套一个区间最小值的数据结构可以得到 s t st st数组

但是发现 s t [ i ] = min ⁡ j = i f i − 1 { f [ j ] } st[i]=\min\limits_{j=i}^{f_i-1}\{f[j]\} st[i]=j=iminfi1{

f[j]}

f f f数组是单调递增的,所以不用数据结构,只需要让 f i f_i fi去更新 f i − 1 f_{i-1} fi1即可

然后我们对于询问 [ l , r ] [l,r] [l,r]

每次从 l l l跳到 s t [ l ] st[l] st[l],最后看看超过 r r r时跳了多少次即可。

但是会超时

没关系,倍增一下 s t st st数组即可,也就是预处理 s t [ i ] [ k ] st[i][k] st[i][k]

表示从 i i i 2 k 2^k 2k步最远能到达哪里

版本一

比赛时憨憨套了线段树求 f f f数组的区间最小值

#include 
using namespace std;#define mid (l+r>>1)#define ls (rt<<1)#define rs (rt<<1|1)#define lson ls,l,mid#define rson rs,mid+1,rconst int maxn = 1e6+10;int a[maxn],n,q;vector
zhi[maxn];void make(){
for(int i=2;i<=100000;i++) for(int j=i;j<=100000;j+=i ) zhi[j].push_back( i );}int nxt[maxn],mi[maxn],su[maxn];void build(int rt,int l,int r){
if( l==r ){
su[rt] = mi[l]; return; } build( lson ); build( rson ); su[rt] = min( su[ls],su[rs] );}int ask(int rt,int l,int r,int L,int R){
if( l>R || r
=L&&r<=R ) return su[rt]; return min( ask(lson,L,R),ask(rson,L,R) );}int st[maxn][22];void init(){
for(int i=1;i<=100000;i++) mi[i] = nxt[i] = n+1; for(int i=n;i>=1;i--) for( auto v:zhi[a[i]] ) {
mi[i] = min( mi[i],nxt[v] ); nxt[v] = i; } build(1,1,n); memset( st,20,sizeof st ); for(int i=1;i<=n;i++) st[i][0] = ask(1,1,n,i,mi[i]-1 ); for(int i=1;i<=20;i++) for(int j=1;j+(1<
<=n;j++) {
int nx = st[j][i-1]; if( nx>n+1 ) st[j][i] = nx; else st[j][i] = st[nx][i-1]; }}void solve(int l,int r){
int ans = 0; for(int i=20;i>=0;i--) if( st[l][i]<=r ) l = st[l][i],ans += (1<
> n >> q; for(int i=1;i<=n;i++) cin >> a[i]; make(); init(); while( q-- ) {
int l,r; scanf( "%d%d",&l,&r); solve(l,r); }}

最小值扫一遍就好了

版本二

#include 
using namespace std;const int maxn = 1e6+10;int a[maxn],n,q;vector
zhi[maxn];void make(){
for(int i=2;i<=100000;i++) for(int j=i;j<=100000;j+=i ) zhi[j].push_back( i );}int nxt[maxn],mi[maxn];int st[maxn][22];void init(){
for(int i=1;i<=100000;i++) mi[i] = nxt[i] = n+1; for(int i=n;i>=1;i--) {
for( auto v:zhi[a[i]] ) {
mi[i] = min( mi[i],nxt[v] ); nxt[v] = i; } mi[i-1] = mi[i]; } memset( st,20,sizeof st ); for(int i=1;i<=n;i++) st[i][0] = mi[i]; for(int i=1;i<=20;i++) for(int j=1;j+(1<
<=n;j++) {
int nx = st[j][i-1]; if( nx>n+1 ) st[j][i] = nx; else st[j][i] = st[nx][i-1]; }}void solve(int l,int r){
int ans = 0; for(int i=20;i>=0;i--) if( st[l][i]<=r ) l = st[l][i],ans += (1<
> n >> q; for(int i=1;i<=n;i++) cin >> a[i]; make(); init(); while( q-- ) {
int l,r; scanf( "%d%d",&l,&r); solve(l,r); }}

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/116008483 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Codeforces Round #717 (Div. 2) A-D题解(热乎的)
下一篇:Codeforces Round #717 (Div. 2) 1516 B. AGAGA XOOORRR(枚举,异或性质)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月05日 02时49分26秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

自动化运维必备——ansible中playbook的编写 2019-04-30
自动化运维必备!ansible的安装及常用模块详解 2019-04-30
Error!启动elasticsearch报错 2019-04-30
springboot定时器的使用 2019-04-30
freeswitch设置账号密码和端口 /conf/autoload_configs/event_socket.conf.xml 2019-04-30
freeswitch添加坐席/usr/local/freeswitch/conf/directory/default 2019-04-30
JavaScript原生开关灯效果 2019-04-30
企业邮箱如何申请注册,邮箱申请如何免费注册? 2019-04-30
微信企业邮箱,手机邮箱格式地址怎么写? 2019-04-30
公司如何申请企业邮箱,公司邮箱怎么申请,公司企业邮箱哪个好? 2019-04-30
电子邮箱账号怎么申请,怎样申请邮箱账号呢 2019-04-30
邮箱怎么发邮件,邮件发信量多少,职场新人怎么发汇报邮件呢? 2019-04-30
企业邮箱注册申请流程,企业邮箱怎么注册账号? 2019-04-30
安全邮箱,企业邮箱哪个好?安全电子邮箱申请 2019-04-30
什么是公司邮箱,如何申请公司邮箱,公司邮箱怎么申请? 2019-04-30
163邮箱域名大全,163邮箱注册申请全流程详解! 2019-04-30
电子邮箱账号申请注册,公司邮件系统哪个好?工作邮箱哪个好? 2019-04-30
怎么申请支持微信登录的企业电子邮箱 2019-04-30
163个人电子邮箱如何申请,邮箱账号都有什么格式你知道吗 2019-04-30
微信企业邮箱登录人口,企业邮箱登陆登录入口 2019-04-30