码迷,mamicode.com
首页 > 其他好文 > 详细

D. Cut(Codeforces Round #717 (Div. 2)题解)

时间:2021-05-24 14:34:30      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:第一个   test   amp   code   round   位置   val   ati   break   

题目链接:D. Cut
思路:首先进行双指针求nxt数组,该nxt数组定义是在该点最远能到达的点,求法是利用双指针,如果发现一个数的质因子在前面出现过,那就说明第一个指针已经得到了他的nxt数组答案。求完nxt数组后,本来我的想法是将每一个下标所对应的能到达的位置,就是一条链写入vector,然后利用二分的方法进行计算,不过该种想法空间会被卡爆,是因为如果前面几个nxt数组都指向同一个数,那么就会多开了几倍的空间。标准做法是利用倍增的思想\(sum[i,j] = sum[sum[i,j-1],j-1]\)\(sum[i,j]\)意为i从跳跃\(2^{j-1}\)次所能到达的答案,求出来之后我们就可以对他的每一次\((l,r)\)询问进行计算,首先枚举出第一个小于r的是需要l跳多少次,再令l=该值,然后就这样进行下去。
\(Code:\)


#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <vector>
#define rep(i, a, b) for (auto i = a; i <= b; ++i)
#define bep(i, a, b) for (auto i = a; i >= b; --i)
#define ch() getchar()
#define pc(x) putchar(x)
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define PI acos(-1)
#define mst fflush(stdout)
using namespace std;
template <typename T>
void read(T& x) {
    static char c;
    static int f;
    for (c = ch(), f = 1; c < ‘0‘ || c > ‘9‘; c = ch())
        if (c == ‘-‘) f = -f;
    for (x = 0; c >= ‘0‘ && c <= ‘9‘; c = ch()) x = x * 10 + (c & 15);
    x *= f;
}
template <typename T>
void write(T x) {
    static char q[65];
    int cnt = 0;
    if (x < 0) pc(‘-‘), x = -x;
    q[++cnt] = x % 10, x /= 10;
    while (x) q[++cnt] = x % 10, x /= 10;
    while (cnt) pc(q[cnt--] + ‘0‘);
}

const int N = 1e5+1;
vector<int>G[N];
int sum[N][33];
int n,q;
int st[N][2],sizes[N];
int a;
bool vis[N];
int prime[N];
int tot ;
int nxt[N],pr[N];
bool v[N];
void getprime(){
    rep(i,2,100000){
        if(!vis[i]){
            prime[++tot] = i;
            if(i>1000)continue;
            for(int j=i*i;j<=100000;j+=i){
                vis[j] = true;
            }
        }
    }
}
void getval(int x,int idx){
    int id = 1;
    while(prime[id] * prime[id] <= x){
        bool flag = false;
        while(x%prime[id] == 0)x/=prime[id],flag = true;
        if(flag)G[idx].pb(prime[id]);
        id++;
    }
    if(x==1)return ;
    G[idx].pb(x);
}
int t[N];
void solve(){
    getprime();
    rep(i,1,100000){
        getval(i,i);
    }
    read(n);read(q);
    rep(i,1,n)read(a),t[i] = a;
    int id = -1;
    rep(i,1,n){
        for(auto p:G[t[i]]){
            if(sizes[p]){id = i;}
            st[p][sizes[p]]=i,sizes[p]++;
        }
        if(id != -1)break;
    }
    int mx = -1;
    if(id == -1){
        mx = n;id = n+1;
    }
    for(auto p:G[t[id]]){if(st[p][0] == id)continue; mx = max(mx,st[p][0]);}
    rep(i,1,mx)nxt[i] = id-1;
    int i = mx+1, j = id+1;
    while(i<=n){
        int idx = -1;
        rep(k,j,n){
            for(auto p:G[t[k]]){
                if(sizes[p] and st[p][sizes[p]-1]>=i){idx = k; }
                //st[p].pb(k);
                if(sizes[p] == 2){
                    st[p][0] = st[p][1];
                    st[p][1] = k;
                }
                else if(sizes[p] == 1){
                    st[p][1] = k;sizes[p] = 2;
                }
                else if(sizes[p] == 0){
                    st[p][0] = k;sizes[p] = 1;
                }
            }
            if(idx != -1)break;
        }
        //第一个成功的
        mx = -1;
        if(idx == -1){
            idx = n+1;
            mx = n;
        }
        for(auto p:G[t[idx]]){
            int lens = sizes[p];
            if(lens == 1)continue;
            if(st[p][lens-2]>=i)mx = max(mx,st[p][lens-2]);
        }
        rep(k,i,mx)nxt[k] = idx-1;
        i = mx + 1, j = idx + 1;
    }
    v[n] = true;
    rep(i,1,n){
        int id = i;
        sum[id][1] = nxt[id]+1;
    }
    rep(i,0,30)sum[n+1][i] = n+1;
    bep(i,n,1){
        rep(j,2,30){
            sum[i][j] = sum[sum[i][j-1]][j-1];
        }
    }
    rep(test,1,q){
        int u,v;
        int ans = 0;
        read(u);read(v);
        bep(i,30,1){
            if(sum[u][i]<=v){
                ans += (1<<(i-1));
                u = sum[u][i];
            }
        }
        write(ans+1);pc(‘\n‘);
    }
}

signed main(){solve();return 0; }


D. Cut(Codeforces Round #717 (Div. 2)题解)

标签:第一个   test   amp   code   round   位置   val   ati   break   

原文地址:https://www.cnblogs.com/violentbear/p/14780238.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!