某天,lostmonkey發明了一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個遊戲。遊戲一開始,lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力係數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ki個裝置,則綿羊被彈飛。綿羊想知道當它從第i個裝置起步時,被彈幾次後會被彈飛。為了使得遊戲更有趣,lostmonkey可以修改某個彈力裝置的彈力係數,任何時候彈力係數均為正整數。
第一行包含乙個整數n,表示地上有n個裝置,裝置的編號從0到n-1,接下來一行有n個正整數,依次為那n個裝置的初始彈力係數。第三行有乙個正整數m,接下來m行每行至少有兩個數i、j,若i=1,你要輸出從j出發被彈幾次後被彈飛,若i=2則還會再輸入乙個正整數k,表示第j個彈力裝置的係數被修改成k。對於20%的資料n,m<=10000,對於100%的資料n<=200000,m<=100000
看15年**看到這道題,介紹的分塊演算法,就是將n個資料分為sqrt(n)塊,那麼每次更新的話最多只要更新元素所在的那一塊,查詢的時候,每次都會移動到下一塊中,最多有sqrt(n)+1塊,那麼每次查詢和更新的代價就是sqrt(n),總共有m次查詢,那麼總體複雜度o(m*sqrt(n))
具體的實現是,to[i]表示每個元素屬於哪一塊,nxt[i]表示i經st[i]步移動到下一塊的什麼地方,st[i]表示該位置移動到下一塊第乙個元素的代價
#include#include#includeusing namespace std;const int maxn=2e5+5;
const int maxm=1e3+5;
int a[maxn],to[maxn],nxt[maxn],st[maxn];
int n,m,l[maxm],r[maxm];
int block,cnt;
inline int read()
return res;
}int solve(int x)
return res;
}int main()
m=read();
for(int i=1;i<=m;i++)
} }return 0;
}
BZOJ 2002 彈飛綿羊 分塊
傳送門ber 不會寫lct 分塊水過 記錄多少次能跳出自己的塊,和跳到的點是哪個 修改時更改本塊x之前的部分 統計時模擬一遍就可以了 lct題解可以看這個人 如下 include include include define n 200050 using namespace std inline i...
bzoj2002 彈飛綿羊 分塊orLCT
先簡單講一下lct做法,每個點以它的到達點為父節點 沒有到達點就連向根 結果就是深度。然後修改就是改變父親,乙個cut再乙個link就好了。然後是分塊。每個點維護它到達它所在塊外面的點,及步數,預處理o n 查詢時o n m 修改時只需要修改x所在塊在x前面的那些點即可,時間o m 因此總時間複雜度...
bzoj2002 彈飛綿羊
lct裸題 給出一棵樹,有修改及詢問,修改操作為修改乙個節點的父親,詢問乙個節點到根的點數。詢問及修改前只需access一遍即可。include include include include include include define rep i,x,y for int i x i y i de...