题解:CF207B3 Military Trainings
题目传送门
题目大意
每个坦克有一个接收半径
思路
考虑
时间复杂度
考虑 st 表预处理出,每一个坦克
这样的话就可以做到在模拟的时候做到
考虑
注意,每次要跳到正好差一次跳到到发送信号的坦克的位置,而且最后到达的位置
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=501010;
ll n,a[N],ans,t[N],fa[N][30],st[N][30];
void init(){
for(ll i=1;i<=2*n;i++)st[i][0]=i;
for(ll j=1;j<=29;j++){
for(ll i=1;i<=2*n-(1<<j)+1;i++){
if(a[st[i][j-1]]<a[st[i+(1<<(j-1))][j-1]])st[i][j]=st[i][j-1];
else st[i][j]=st[i+(1<<(j-1))][j-1];
}
}
}
ll query(ll l,ll r){
ll k=log2(r-l+1);
if(a[st[l][k]]<a[st[r-(1<<k)+1][k]])return st[l][k];
else return st[r-(1<<k)+1][k];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i+n]=a[i];
}
for(int i=1;i<=2*n;i++)a[i]=max(i-a[i],1ll);
init();
for(int i=1;i<=2*n;i++){
fa[i][0]=query(a[i],i);
}
for(int j=1;j<=29;j++){
for(int i=1;i<=2*n;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
for(int i=1;i<=n;i++){
ll cnt=2;
ll now=i+n-1;
if(a[now]<=i){
ans++;
continue;
}
for(ll j=29;j>=0;j--){
if(a[fa[now][j]]>i)cnt+=(1<<j),now=fa[now][j];
}
ans+=cnt;
}
cout<<ans;
return 0;
}