0
点赞
收藏
分享

微信扫一扫

ST表&&D. New Year Concert

八怪不姓丑 2022-02-06 阅读 103
算法

【传送门】Problem - D - Codeforces

大概题意就是,一个数组a,每一个区间gcd(区间左起l,右终于r),当这个区间最大公约数 == r - l + 1 时,这个区间是boring 的,可以修改区间某值,使这个区间不boring, 求使这个数组任意区间都是不boring要修改几个值,然后按照到某位置要最少修改几个值输出。

解:

首先很容易想明白,如果一个区间是boring 的, 那么我们可以修改某个数为任意的大质数,要使数量最少,贪心下,然要修改的值尽量后。然后每个修改后的值就相当于一面墙。然后用st表来维护区间gcd

#include<bits/stdc++.h>
using namespace std;
const int N = 2000010;
int  a[N], mn[N], gd[N][22];

int q, n;

void init(){
    mn[0] = -1;
    for(int i = 1; i <= n; i++){
        mn[i] = ((i & (i - 1)) == 0) ? mn[i - 1] + 1 : mn[i - 1];
        gd[i][0] = a[i];
    }
    for(int j = 1; j <= mn[n]; j++){
        for(int i = 1; i + (1 << j) - 1 <= n; i++){
            gd[i][j] = __gcd(gd[i][j-1], gd[i + (1 << (j - 1) + 1)][j - 1]);
        }
    }
}
inline int qgd(int L, int R){
    int k = mn[R - L + 1];
    return __gcd(gd[L][k], gd[R - (1 << k) + 1][k]);
}

signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    init();
    int ans = 0;
    int maxr = -1;
    int pt = 0;
    for(int i = 0; i < n; i ++){
        while(pt < i && qgd(pt, i) < i - pt + 1) pt++;
        if(qgd(pt, i) == i - pt + 1){
            if(pt > maxr){
                ++ans;
                maxr = i;
            }
        }
        cout << ans << " ";
    }
}


 

举报

相关推荐

0 条评论