标签:第一个 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