維護乙個棧,每次區間壓棧,單點彈棧,區間詢問棧頂的元素和。
如果沒有彈棧的操作的話,我們每一次只需要在一顆線段樹上面區間賦值即可。
加上彈棧操作,我們每次就需要知道當前棧頂元素的上乙個元素是什麼,考慮用主席樹來維護每乙個時刻每乙個位置的最近一次的修改位置。
假設當前的時間為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<<"="<>1)
typedef long long ll;
using namespace std;
void file()
templatevoid 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;
int main()
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...