維護乙個棧,每次區間壓棧,單點彈棧,區間詢問棧頂的元素和。
如果沒有彈棧的操作的話,我們每一次只需要在一顆線段樹上面區間賦值即可。
加上彈棧操作,我們每次就需要知道當前棧頂元素的上乙個元素是什麼,考慮用主席樹來維護每乙個時刻每乙個位置的最近一次的修改位置。
假設當前的時間為x且我們需要彈棧,那麼我們需要先查詢得到最近的一次時間y,然後查詢y-1的修改時間z,那麼我們就得到了棧頂下面的元素的修改時間。
然後我們需要將x點的這個元素的時間改為z,然後更新查詢線段樹上的答案即可。
不難發現我們實際上是向前維護了乙個最近修改時間的鍊錶,由於主席樹的繼承性質,直接查詢y-1使得我們的答案是正確的。
/************************************====
* author : ylsoi
* time : 2019.3.10
* problem : uoj218
* e-mail : [email protected]
* ***********************************=*/
#include
#define rep(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define drep(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define mid ((l+r)>>1)
typedef
long
long ll;
using
namespace std;
void
file()
template
<
typename t>
void
read
(t &_)
string proc()
const
int maxn=
5e5+10;
int n,m,ty,ans,root[maxn]
,tot,w[maxn]
;struct segment_tree
}void
update
(int o,
int l,
int r,
int l,
int r,
int x,
int y)
}int
query_sum
(int o,
int l,
int r,
int l,
int r)
}int
query_las
(int o,
int l,
int r,
int p)
#undef lc
#undef rc
}t1;
struct chairman_treet[maxn*
120]
;void
insert
(int
&o,int l,
int r,
int l,
int r,
int x)
}int
query
(int o,
int l,
int r,
int p)
}t2;
intmain()
else
if(op==2)
}else
/*rep(j,1,n)printf("%d ",t1.query_sum(1,1,n,j,j));
printf("\n");*/
}//cerr}
uoj218 火車管理 主席樹
維護乙個棧,每次區間壓棧,單點彈棧,區間詢問棧頂的元素和。如果沒有彈棧的操作的話,我們每一次只需要在一顆線段樹上面區間賦值即可。加上彈棧操作,我們每次就需要知道當前棧頂元素的上乙個元素是什麼,考慮用主席樹來維護每乙個時刻每乙個位置的最近一次的修改位置。假設當前的時間為x且我們需要彈棧,那麼我們需要先...
UOJ 218 UNR 1 火車管理
維護一顆主席樹 火車入棧相當於區間修改,彈棧相當於返回歷史版本 維護線段樹區間求和 ps 之前沒把 放上來 extra的最後乙個點re,orz蒟蒻無能為力 include include include include include const int maxn 600005 const int ...
UOJ 218 UNR 1 火車管理
注意記憶體有些卡,有一些技巧 1.首先對於查詢的線段樹是全域性的,不需要動態開點 2.對於線段樹中的乙個節點 x 如果它的左右兒子都沒有兒子,那麼下一次做區間覆蓋時,就不需要對 x 新建兩個節點 include define lo o 1 define ro o 1 1 using namespac...