高手訓練 線段樹 棧的維護

2022-04-01 05:40:22 字數 2318 閱讀 3581

time limit: 20 sec  memory limit: 512 mb

從前有個棧,一開始是空的。

你寫下了 m 個操作,每個操作形如 k v :

若 k = 0,代表往棧頂加入乙個數 v

若 k = 1,則代表從棧頂彈出 v 個數,如果棧中的元素少於 v 個,則全部彈出。

接著你又進行了 q 次修改,每次你會選擇乙個操作,並且修改它的兩個引數。

在每次修改後,你都要求出如果依次執行這些操作,最後棧中剩下的元素之和。

第一行兩個正整數 m,q,分別表示運算元和修改次數。

接下來 m 行,每行兩個整數 k,v,代表乙個操作。

接下來 q 行,每行三個正整數 c,k,v,表示將第 c 個操作的引數修改為 k 和 v。

輸出 q 行,每行乙個整數,代表依次執行所有操作後棧中剩下的元素之和。

5 20 3

0 20 3

1 10 5

1 0 3

1 0 1108

m,q ≤ 2×1e5, v ≤ 1e4

這個嘛。。。

其實一看覺得不像是線段樹

但是這又是修改,又是查詢的awa

不找他找誰呢awa

如果想要按照線段樹的方法來搞的話,不考慮資料的其他性質,可以發現,我們能維護的只有他之前給的操作。。。

因為這個操作其實是就是答案的序列。。

而且題目的修改也是針對這個東西的。

所以我覺得應該就是要維護這個東西的awa

get到了新的線段樹維護方法awa,妙啊

進入正題

以操作順序為下標,建立一棵線段樹

發現題目中的修改的區間影響的範圍非常大,是從這個點開始,一直到結尾的

考慮修改的方法。

在建樹是,我們上傳的東西其實是假設沒有修改操作時候的棧的答案。

有以下幾點,是要記錄的

1.乙個區間中,又增加有刪除的數字,是沒有意義的,可以忽略

2.維護區間和

3.除了被抵消的數,還需要刪除的數  這些操作只能有前面的數來補

4.除了被抵消的數,還需要新增的數  這些操作只能被後面的操作給刪掉 

這些其實就是我們應該考慮的全部的情況了。

我們最終的目標就是區間累加和

然後就是維護的問題awa

剩下就是維護的問題。

這兩個式子,第乙個是最終刪除的數,第二個是最終新增的數。

合併時,右區間的和是不會受到影響的,但是因為右區間的del(刪除的數),左區間的一些數可能會被刪去。

於是這麼乙個問題,對於操作區間p,之後要刪x個數,刪完以後這個區間的和是多少。即為​​​

cal(p,x)

如果add_p<=x顯然這個區間被刪完了,就是0

如果add_rs>=x,只要刪右區間的數就好了,問題轉化為乙個子問題

否則右區間的數要全部刪掉,然後再在左區間刪。

然後就沒了awa

code

#include#define ll long long

using

namespace

std;

int n,m,q,a[300001

];struct

edge

t[8000001

];inline ll read()

int cal(int q,int

x)void push_up(int

q)void build(int q,int l,int

r)

int mid=l+r>>1

; build(q*2

,l,mid);

build(q*2+1,mid+1

,r);

push_up(q);

}void modiffy(int q,int x,int k,int

v)

else

return

; }

int mid=(t[q].l+t[q].r)>>1

;

if(x<=mid)modiffy(q*2

,x,k,v);

else modiffy(q*2+1

,x,k,v);

push_up(q);

}int

main()

build(

1,1,n);

for(int i=1;i<=q;i++)

return0;

}

調了乙個小時

痛苦萬分。。。

線段樹真的是乙個字元寫錯了就炸了。。。

唉這道題主要是給我了一種新的建樹方法

其實線段樹的統計和更改操作可以通過一定的方法來適應題目,解決問題。

陶陶摘蘋果 線段樹維護單調棧

題庫字尾為contest 132 problem 2 目前本人比較偏向的板子中,核心是乙個calc函式,傳入兩個引數 rt 和 w w 代表 rt 節點所統領的區間所受到的限制的值。如果左兒子的最大值比 w 大,那麼就遞迴左兒子,右兒子不必再遞迴,因為單調遞增,右兒子的最小值一定大於等於左兒子的最大...

線段樹 維護序列

老師交給小可可乙個維護數列的任務,現在小可可希望你來幫他完成。有長為 n 的數列,不妨設為 a1,a2,an。有如下三種操作形式 把數列中的一段數全部乘乙個值 把數列中的一段數全部加乙個值 詢問數列中的一段數的和,由於答案可能很大,你只需輸出這個數模 p 的值。輸入格式 第一行兩個整數 n 和 p ...

線段樹訓練

d hdu6703 題意 給乙個長度為n且互不相同的陣列。有m個操作,操作1是給a pos 加上1000000,操作2是查詢在1 r沒有出現過同時大於k的值,並使其最小。一種做法就是權值線段樹,每個節點維護該權值的下標,那麼原題就轉化為查詢 k,n 範圍內大於r的值,位置盡量靠左,即可使答案最小。i...