首页 > 其他分享 >区间 题解

区间 题解

时间:2024-10-02 09:49:41浏览次数:9  
标签:__ 题解 bmod leq ans 区间 复杂度

题意简述

求长度为 \(n\) 的序列 \(a\) 的最长连续子序列 \([l, r]\),满足 \(\exists i \in [l, r], \gcd(a_l, \ldots, a_r) = a_i\)。

\(1 \leq n \leq 4 \times 10 ^ 6\),\(1 \leq a_i \leq 10^{18}\)。

题目分析

根据 \(\gcd(a, b) = a\) 等价于 \(b \bmod a = 0\),这个区间的限制等价于 \(\forall j \in [l, r], a_j \bmod a_i = 0\)。进而我们发现,可以在 \(a_i\) 处统计答案,将问题转化为两部分。即,我们需要求出 \(l_i\),表示最小的位置,满足 \(\forall j \in [l_i, i], a_j \bmod a_i = 0\),\(r_i\) 同理。

我们直接扫是 \(\Theta(n ^ 2)\) 的,看看有没有地方重复计算了。显然是有的,比如有个 \(k < j\),并且 \(a_k \bmod a_j = 0\),我们扫过 \(a_j \bmod a_i = 0\) 后,就不用去扫 \(a_k\) 了。于是,我们想到,可以直接从 \(l_j - 1\) 继续扫下去。这样的时间复杂度如何保证呢?考虑这个算法的本质,就是维护了一个栈,栈中相邻的都不能整除。当我们新加入一个 \(a_i\) 时,从 \(l_j - 1\) 继续扫下去,可以看做是弹栈,因为之后就不会访问到 \(j\) 了。所以,这样的时间复杂度是线性 \(\Theta(n)\) 的。

代码

#include <cstdio>

const int MAX = 1 << 28;
char buf[MAX], *p = buf;
#ifdef XuYueming
# define fread(_, __, ___, ____)
#else
# define getchar() *p++
#endif
#define isdigit(x) ('0' <= x && x <= '9')
#define __yzh__(x) for (; x isdigit(ch); ch = getchar())
template <typename T>
inline void read(T &x) {
    x = 0; char ch = getchar(); __yzh__(!);
    __yzh__( ) x = (x << 3) + (x << 1) + (ch ^ 48);
}

const int N = 4000010;

using lint = long long;

int n, ans, stack[N], *top = stack, L[N], *Li = L;
lint val[N];

signed main() {
    #ifndef XuYueming
    freopen("interval.in", "r", stdin);
    freopen("interval.out", "w", stdout);
    #endif
    fread(buf, 1, MAX, stdin);
    read(n);
    register int i;
    for (i = 1; i <= n; ++i) {
        read(val[i]);
        while (top != stack && val[*top] % val[i] == 0) --top;
        *++Li = *top + 1, *++top = i;
    }
    *(top = stack) = n + 1;
    for (i = n; i; --i) {
        while (top != stack && val[*top] % val[i] == 0) --top;
        if (*top - *Li > ans)
            ans = *top - *Li;
        *++top = i, --Li;
    }
    printf("%d", ans);
    return 0;
}

标签:__,题解,bmod,leq,ans,区间,复杂度
From: https://www.cnblogs.com/XuYueming/p/18444415

相关文章

  • 题解 P2726 【[SHOI2005]树的双中心】
    首先,我们会有一个很简单的想法,枚举断边,产生两棵子树,然后在两棵树内分别求带权重心,计算贡献,这样的话复杂度是\(O(n^2)\)的。那么我们要好好利用$h\leq100$的性质。考虑\(sze[u]\)为带权重量,\(g[u]\)为以\(u\)为根的树,所有点都到\(u\)的代价。所以\(g[u]=\sum\l......
  • AT_abc373_e 的题解
    (一)二分套二分。(感觉是一个很麻烦的做法。)题目问的是让额外给的票最少,考虑二分答案。设二分的答案为\(x\),该候选人原来的得票为\(v\),想要超过他至少要\(x+v+1\)。同时用前缀和维护区间和。第一种情况为该候选人在前\(m\)个人中,如下图所示。绿色箭头为被讨论的人,蓝色箭......
  • Acwing-246. 区间最大公约数
    本蒟蒻的第二篇题解qwq.题目大意:给定一个长度为\(N\)的数组,需要在数组上进行两种操作:1.Clrd,表示把\(A[l],A[l+1],...,A[r]\)都加上\(d\).2.Qlr,表示询问\(A[l],A[l+1],...,A[r]\)的最大公约数\((GCD)\).错误解法:如果你是一个只会打暴力的小蒟蒻(就像我),看......
  • 优美函数 题解
    题意简述给你函数\(f\):\[f(x,y,u)=\left\{\begin{array}{rcl}u-y,&x=1\\u,&1<x\ley,\\gcd(x,y)=1\\-x\cdoty,&x\neq1,\\gcd(x,y)=x\\0,&\text{otherwise}.\end{array}\right.\]对于一个长度为\(n\)的序列......
  • ABC 模拟赛 | A Passing Contest 001题解记录(A,B,C,D)
    比赛链接https://www.luogu.com.cn/contest/126344[APC001]A-CT不必多说,多次取模#include<iostream>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<deque>#include<math.h>#include<map>......
  • CF1214G Feeling Good 题解
    题目链接点击打开链接题目解法我真菜啊,感觉每一步都不难,但一步都没想到/yun考虑两行\(x,y\)什么时候可以构造出合法的矩形?即\(x\)中需要有\(y\)对应位置为\(0\)的\(1\),\(y\)中需要有\(x\)对应位置为\(0\)的\(1\)归纳一下,\(x\)不是\(y\)的子集且\(y\)不......
  • CF2018E2 Complex Segments (Hard Version) 题解
    题目描述\(T\)组数据,给定\(n\)条线段\([l_i,r_i]\),称一个线段集合是复杂的,当且仅当:它可以被划分成若干个大小相等的线段组。两条线段相交当且仅当它们在同一组。求用这\(n\)条线段构成的复杂线段集合的最大值。数据范围\(1\len,\sumn\le3\cdot10^5\)。\(1\l......
  • CF280C Game on Tree题解
    题目描述给定一棵有根树,结点编号从1到n。根结点为1号结点。对于每一次操作,等概率的选择一个尚未被删去的结点并将它及其子树全部删去。当所有结点被删除之后游戏结束。也就是说,删除1号结点后游戏即结束。要求求出删除所有结点的期望操作次数。不是哥们,我好不容易国庆......
  • 题解:AtCoder Beginner Contest AT_abc373_d ABC373D Hidden Weights(格式美化版)
    题目传送门题目翻译给你一个NNN个点,MMM条边的有向图,其中边有边......
  • CF429E Points and Segments 题解
    题目链接点击打开链接题目解法真难啊/yun把区间染成红色看作区间\(+1\),染成蓝色看作区间\(-1\),要求是每个点上的数\(\in\{-1,0,1\}\)可以选择的数有\(-1,1\)不太好做,我们考虑将限制变成每个点上的数只能为\(0\)我们记经过点\(x\)的线段数量为\(cnt_x\)如果\(cnt......