1. 程式人生 > >【codevs2333】彈飛綿羊

【codevs2333】彈飛綿羊

std 所有 clas 兩個 需要 時間復雜度 name 初始化 查詢

原本這個題的正解是lct,可是自從這個題被人發現可以用分塊做,然後就成為了分塊的練習題233333,而且雖然lct的時間復雜度是nlogn的,可是因為常數太大,反而跑不過分塊,挺有意思的

這個題我們可以設置sqrt(n)個塊,然後維護塊內每個元素到下一個塊的最小步數和到到達下一個塊的第一個點,然後這樣每次查詢、修改的時間復雜度最壞是sqrt(n),所以最後時間復雜度是m√n

PS:這個題的題號也挺有意思的23333333

#include<iostream>
#include<cstring>
#include<cstdio>
#include
<cmath> using namespace std; int n,m,ne[200020],g,xi[200020],bu[200020],x,y,z; inline void ask(int x)//詢問需要多少步 { int re=0; while(1)//一直跳,直到能夠跳出n { re+=bu[x]; if(!ne[x])//因為 能直接跳到n的都沒賦值 break; x=ne[x]; } printf("%d\n",re); } inline void cha(int
wei,int zhi)//進行修改 { xi[wei]=zhi;//先改完裝置的彈力系數 for(int i=wei;i>=(((wei-1)/g+1)-1)*g+1;i--)//所有關於這個塊的信息都要更新 { if((i+xi[i]-1)/g+1==(i-1)/g+1)//如剛才的初始化 bu[i]=bu[i+xi[i]]+1,ne[i]=ne[i+xi[i]]; else bu[i]=1,ne[i]=i+xi[i]; } } int main() { scanf(
"%d",&n); g=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&xi[i]); for(int i=n;i>0;i--) { if(i+xi[i]>n)//因為我們輸入的是從1到n,相當於整體都加1了,所以大於n bu[i]=1; else if((i+xi[i]-1)/g+1==(i-1)/g+1)//如果這兩個點位於同一個塊,說明從這個彈射裝置出發不能直接飛出這個塊 bu[i]=bu[i+xi[i]]+1,ne[i]=ne[i+xi[i]];//因此它的步數相當於它跳到的下一個塊跳出去這個塊的步數+1,從它出發跳到塊外的第一個點是下個塊的答案 else bu[i]=1,ne[i]=i+xi[i];//否則說明從這個點能夠直接跳出這個塊 } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); y++;//整體加1 if(x==1) ask(y); else scanf("%d",&z),cha(y,z); } }

【codevs2333】彈飛綿羊