JoyOI1473 校門外的數3 (線段樹)

2021-08-19 10:17:22 字數 2203 閱讀 1964

題意很簡單

一開始想用乙個bitset維護,明顯這個是超記憶體的。但是我為什麼還要寫

然後想了一下,能不能維護每次種樹的左右區間來寫,然而發現並不行。

接著想,維護種類和維護區間沒辦法了,能不能在種樹的次數上下功夫呢?

我想維護乙個種了樹和沒種樹的線段樹,詢問就是查詢區間內中了樹的最大值和沒種樹的最小值,最後做乙個差,這樣的話樣例是過的。寫完交上去wa了,自己想了乙個樣例吧自己叉掉了。為什麼我不提前想一下呢?

然後就想,肯定是維護種植的次數的關係。苦苦思考無果。看了看大佬的題解,思路泉湧思路如下:

還是思考種了樹和沒種樹的關係,其實他們互為補集,這是非常明顯的。

每次種樹,所種樹的種類也是不同的,這也是顯而易見的,也就是如果當前種了n次樹,那麼現在街道上一定有n種樹對吧?

好了,所以對於每一次查詢,我們只需要知道,對於這段區間,有多少種樹是重複的,然後做差就可以得到結果了。

所以問題就轉換為,如何維護所種樹是重複的。由於每次種樹,不種樹的區間被種樹的區間分為了兩段,所以這樣維護左右兩半部分比較方便,況且對於下面求解問題也是較為簡便的。所以這裡要分左右兩部分計算。

下面舉例說明演算法的思想。

1. 街道長為[1,100],首先在[30,60]種樹,那麼左邊沒有種樹的區間l[1,29],右邊r[61,100],我們將這個區間分別加一(分別的意思是左右要用不同的線段樹維護)。

2. 假如我們要查詢[20,40]種樹的資訊。由於現在種樹中了1次,所有tot=1。關鍵來了,想辦法去重,重複的如何計算呢?在沒有種樹的左區間中查詢右端點,在沒有種樹的右區間中查詢左端點,也就是在l[1,29]中查詢60,在r[61,100]中查詢30,顯然,均為0 ,所以結果就是tot-0-0 = 1

3. 大家可以舉例子自己嘗試,關鍵就是【在沒有種樹的左區間中查詢右端點,在沒有種樹的右區間中查詢左端點】,然後用種樹的從次數減去即可

#include

using

namespace

std;

const

int nmax = 60001;

const

int inf = 0x3f3f3f3f;

typedef

long

long ll;

typedef

struct

}tree;

tree tree[nmax<<2];

int hashback[nmax];

int n,m;

inline

void pushdown(int rt)

if(tree[rt].rr)

}void build(int l, int r, int rt)

build(l,tree[rt].mid(),rt<<1);

build(tree[rt].mid() + 1 ,r, rt<<1|1);

}void lupdate(int l, int r, int rt)

// if(tree[rt].l == tree[rt].r) return;

if(tree[rt].l != tree[rt].r) pushdown(rt);

if(l<=tree[rt].mid()) lupdate(l,r,rt<<1);

if(r>tree[rt].mid()) lupdate(l,r,rt<<1|1);

// lupdate(l,r,rt<<1);

// lupdate(l,r,rt<<1|1);

}void rupdate(int l, int r, int rt)

// if(tree[rt].l == tree[rt].r) return;

if(tree[rt].l != tree[rt].r) pushdown(rt);

if(l<=tree[rt].mid()) rupdate(l,r,rt<<1);

if(r>tree[rt].mid()) rupdate(l,r,rt<<1|1);

// rupdate(l,r,rt<<1);

// rupdate(l,r,rt<<1|1);

}int lquery(int pos, int rt)

int rquery(int pos , int rt)

int main()else

}return

0;}

tyvj1473 校門外的樹3

tyvj1473 這道題可以用兩個樹狀陣列來做把每次更新的端點分別插入兩個樹狀陣列,在查詢區間時,之前更新的區間會對當前查詢區間產生影響的條件是 更新的末端點大於查詢的始端點且更新的始端點小於等於查詢的末端點,那麼由於如果某次更新的始端點大於查詢的末端點,那麼這次更新的末端點也大於查詢的末端點 因而...

TYVJ1473 校門外的樹3

思路 維護兩個樹狀陣列,乙個記錄種樹區間左端點,乙個記錄右端點。每次詢問查詢 看不見的樹區間 即右端點小於查詢區間左端點和左端點小於查詢區間右端點。1 include2 include3 include4 inline int getint 11const int n 50001 12 intn 1...

POJ校門外的數

總時間限制 1000ms 記憶體限制 65536kb 描述某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它...