Codeforces 1632D New Year Concert 数据结构维护尺取

本文介绍了一道编程题目,涉及序列处理和动态规划。题目要求找到一个序列,使得序列中没有无聊子序列(即最大公约数等于子序列长度),并通过修改序列中的数字来实现。解决方案是将数字改为大质数,并使用贪心策略和区间最大公约数查询数据结构(如线段树)来确定需要修改的数字个数。文章提供了详细的算法思路和代码实现。
摘要由CSDN通过智能技术生成

文章目录


题目地址

题意

定义一个数字序列中如果有一个连续子序列满足这个子序列的最大公约数等于其长度,则称该序列为无聊的。在可以任意修改数字的情况下,对序列 x x x存在函数 f ( x ) f(x) f(x)定义为使得该序列不无聊至少需要修改数字的个数。给定一个序列,求这个序列每个前缀的 f f f函数值。

题解

我们发现可以将数字改为大质数,这样包含这个数字的区间就不可能无聊。
因此假设长度为 i − 1 i-1 i1的前缀不无聊,但是长度为 i i i的前缀无聊,则仅需修改第 i i i个数的贪心显然成立。
再根据最大公约数随序列长度增加而减小的单调规律,在右端点不动的情况下,左端点右移,则 g c d gcd gcd不降。那么只需要不断右移左端点,直到 g c d ≥ 区 间 长 度 gcd\geq 区间长度 gcd,然后判断是否相等以及这一段区间是否均未被修改过,若判定成功即修改右端点。这样一来就做完了。
区间 g c d gcd gcd用st表或者线段树这样的数据结构便可处理,主函数做法用二分或者尺取都可以。

#include<bits/stdc++.h> //Ithea Myse Valgulious
const int yuzu=2e5;
typedef ll fuko[yuzu|10];
fuko a,lg2={-1};
struct sp_table {
  fuko gcd[21];
  void init(int n) {
    for (int i=1;i<=n;++i) gcd[0][i]=a[i];
    for (int i=1;i<=19;++i) {
      for (int j=1;j+(1<<i)-1<=n;++j)
        gcd[i][j]=__gcd(gcd[i-1][j],gcd[i-1][j+(1<<i-1)]);
    }
  }
  ll query(int l,int r) {
    int k=lg2[r-l+1];
    return __gcd(gcd[k][l],gcd[k][r-(1<<k)+1]);
  } 
}zw;
int main() {
  int n,i,j;
  read(n);
  for (i=1;i<=n;++i) a[i]=read(),lg2[i]=lg2[i>>1]+1;
  zw.init(n);
  int ans=0,l=1,ml=-1;
  for (i=1;i<=n;++i) {
    for (;l<i&&zw.query(l,i)<i-l+1;++l);
    if (zw.query(l,i)==i-l+1&&l>ml) {
      ++ans,ml=i;
    }
    printf("%d ",ans);
  }
}

谢谢大家。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值