線段樹 跳蚤

2022-04-04 22:00:11 字數 1756 閱讀 9413

nirobc 姐姐奴役了一群跳蚤,並隨時把它們丟到一台圖靈機的紙帶上。

一開始,紙帶上沒有跳蚤,每乙個時刻,nirobc 姐姐可能做以下三個操作之一:

在位置x 放置乙隻每次向右(座標增大方向)跳t 格的跳蚤。

命令所有跳蚤向右跳躍一次,跳躍的距離為各自的t。

給定區間[l,r],求該區間內跳蚤的個數。

第一行乙個正整數q,表示操作個數。

接下來q 行,這q 行中的第i 行含有若干個整數,描述第i 個操作。

(1) 若第乙個整數為1,則緊跟兩個整數xi 和ti,表示在xi 的位置放置乙隻每次向右跳躍ti 格的跳蚤。

(2) 若第乙個整數為2,則命令所有跳蚤向右跳躍一次。

(3) 若第乙個整數為3,則緊跟兩個整數li 和ri,你需要輸出此時區間[li, ri]中跳蚤的數量。

對於每乙個3 號操作,輸出一行乙個整數,表示該詢問的答案。

①對於步長大於200的跳蚤(大步長),最多跳500次就會出界,所以直接模擬,用樹狀陣列維護跳蚤位置。複雜度o(500 * 1e5 * log(1e5))

②對於步長小於等於200的跳蚤(小步長),將這些跳蚤以步長t分類,對每個t建一顆線段樹,以維護步長為t的跳蚤的起始位置。

比如某個操作1是要在x處插入乙個步長位t的跳蚤,而在此之前已經實施了times次操作2(即跳躍),則可等價為這個操作1是在最開始實施(即所有操作之前)要在x-t * times處插入乙個步長為t的跳蚤。這樣將所有步長為t的跳蚤都統一跳了times步,而起始位置都做了相應的等價轉換。

在查詢[l,r]區間的小步長跳蚤個數時,若之前已實施times次操作2,則對步長t的跳蚤,相當於查詢起始位置在[l-t * times,r-t * times]的跳蚤個數,並統計到答案裡。複雜度o(200 * 1e5 * log(1e5))

#include#pragma gcc optimize(2)

#pragma gcc optimize(3,"ofast","inline")

#define lowbit(x) x&(-x)

using namespace std;

const int n=1e5;

int c[100005];

inline void add(int pos,int val)

}inline int getsum(int pos)

return ret;

}pairp[100005];

int tot=0;

int rt[205];

struct nodenode[3000005];

int ls[3000005],rs[3000005];

int id=0;

inline int newnode(int l,int r);

return id;

}void addval_to_point(int k,int pos,int val)

int mid=(node[k].l+node[k].r)>>1;

if(pos<=mid)

else

node[k].sum=node[ls[k]].sum+node[rs[k]].sum;

}int ask_interval_sum(int k,int l,int r)

int main()

else

}else if(op==2)

}tot=_tot;

}else

printf("%d\n",ans);}}

return 0;

}

跳蚤(線段樹)

nirobc 姐姐奴役了一群跳蚤,並隨時把它們丟到一台圖靈機的紙帶上。一開始,紙帶上沒有跳蚤,每乙個時刻,nirobc 姐姐可能做以下三個操作之一 在位置x 放置乙隻每次向右 座標增大方向 跳t 格的跳蚤。命令所有跳蚤向右跳躍一次,跳躍的距離為各自的t。給定區間 l,r 求該區間內跳蚤的個數。第一行...

線段樹 02 構建線段樹

public inte ce merger 不能再縮小的基本問題是 對treeindex指向的節點的情況進行討論 public class segmenttree 在treeindex的位置建立表示區間 l.r 的線段樹 private void buildsegmenttree int treei...

線段樹 01 線段樹基礎

物理上 public class segmenttree public int getsize public e get int index 返回完全二叉樹的陣列表示中,乙個索引所表示的元素的左孩子節點的索引 private int leftchild int index 返回完全二叉樹的陣列表示中...