HDU 4032 線段樹單點更新 區間最值

2021-09-20 18:41:15 字數 1866 閱讀 8905

1.題目鏈結。題目大意:在一段長為n的線段上,有m個操作。某人起始點在0,現在他想吃餡餅,m個操作種,第一種為在某個點長出來乙個餡餅,第二個為這個人要開始吃餡餅。吃餡餅的時候,總是找距離的當前點最近的那個點去吃,如果發現有兩個最近點,那麼就按照上一次的方向去吃。問最後操作完,這個人走了多長的距離?

2.首先分析,我們需要維護的變數肯定是有curpos,當前點在哪。然後對於當前點,我們需要找到最近的點在哪,那麼就是找一下左邊有餡餅並且座標最大的,右邊有餡餅並且座標最小的。ok,模型已經抽象出來了,其實就是維護當前點的兩個最值。這個最值不是區間的最大最小值,而是距離這個點出現餡餅座標的最大最小值,那麼對於每乙個吃餡餅的操作,我們只需要查詢[0,curpos]的最大值,[pos,n]的最小值,看看哪個更近。如果相同,就按照之前的方向走。所以還有維護乙個pre的資訊,每次吃餡餅操作之後,我們需要維護四個資訊:當前點在哪?當前方向在哪?已經走了多遠?這個點的數量減一。線段樹維護即可。

#includeusing namespace std;

#pragma warning(disable:4996)

const int maxn = 100010;

const int inf = 1e9 + 10;

struct node

seg[maxn * 3];

void build(int i, int l, int r)

int mid = (l + r) >> 1;

build(i << 1, l, mid);

build(i << 1 | 1, mid + 1, r);

seg[i].maxx = max(seg[i << 1].maxx, seg[i << 1 | 1].maxx);

seg[i].minn = min(seg[i << 1].minn, seg[i << 1 | 1].minn);

}void add(int i, int t)

int mid = (seg[i].l + seg[i].r) >> 1;

if (t <= mid)

add(i << 1, t);

else

add(i << 1 | 1, t);

seg[i].maxx = max(seg[i << 1].maxx, seg[i << 1 | 1].maxx);

seg[i].minn = min(seg[i << 1].minn, seg[i << 1 | 1].minn);

}void del(int i, int t)

return;

} int mid = (seg[i].l + seg[i].r) >> 1;

if (t <= mid)

del(i << 1, t);

else

del(i << 1 | 1, t);

seg[i].maxx = max(seg[i << 1].maxx, seg[i << 1 | 1].maxx);

seg[i].minn = min(seg[i << 1].minn, seg[i << 1 | 1].minn);

}int querymax(int i, int l, int r)

int querymin(int i, int l, int r)

int main()

else

else if (t1 != -1 && t2 == inf)

else if (t1 != -1 && t2 != inf)

else if (curpos - t1 < t2 - curpos)

else

else}}

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

} return 0;

}

單點更新,區間查詢線段樹

線段樹的空間複雜度是4n include include include using namespace std const int maxn 100005 const int inf 0x3f3f3f3f int n,a maxn struct node 結點 tree maxn 4 樹結點儲存陣...

hdu 3308 線段樹單點更新 區間合併

學到兩點 1 以區間端點為開始 結束的最長.似乎在dp也常用這種思想 2 分類的時候,明確標準逐層分類,思維格式 條件一成立 else else else 上面的這種方式很清晰,如果直接想到那種情況iif 條件一 條件二 就寫,很容易出錯而且把自己搞亂,或者情況不全,我就因為這wa了幾次 3 wa了...

hdu 1540(線段樹單點更新 區間合併)

解題思路 這一題要求的是連續區間,所以可以把它的子區間合併,這裡運用線段樹,但是在儲存節點資訊的方面要做一點修改 lsum 從這個區間的左端點往右能夠找到的最大連續區間 rsum 從這個區間的右端點往左能夠找到的最大連續區間 msum 表示這整個區間能夠找到的最大連續區間 sum 0表示這個區間還沒...