京東:第五代無人智慧快遞車在上海開展無接觸配送,首批超 8 萬件母嬰物資緊急運達
阿新 • • 發佈:2022-04-08
笛卡爾樹
定義
同時滿足堆和二叉搜尋樹的性質。即對於每個節點有兩個鍵值 \(w,k\) 。其中 \(w\) 滿足堆的性質,而 \(k\) 滿足二叉搜尋樹的性質。
構造
我們把點按照 \(k\) 排序,那麼我們新加入的點直接往右鏈放即可。因此我們用棧維護這個過程。
具體來說棧維護右鏈,且內部元素的 \(w\) 值非嚴格單調遞增。如果當前新打算加入的元素的 \(w\) 比棧頂小,那麼一直彈棧。彈不了了就直接把當前點往右鏈上接。被彈出的部分接在新加入的點的左子樹即可。其實是比較自然的。
#include<bits/stdc++.h> #define ll long long #define db double #define filein(a) freopen(#a".in","r",stdin) #define fileot(a) freopen(#a".out","w",stdout) #define sky fflush(stdout); #define gc getchar #define pc putchar namespace IO{ inline bool blank(const char &c){ return c==' ' or c=='\n' or c=='\t' or c=='\r' or c==EOF; } inline void gs(char *s){ char ch=gc(); while(blank(ch) ) {ch=gc();} while(!blank(ch) ) {*s++=ch;ch=gc();} *s=0; } inline void gs(std::string &s){ char ch=gc();s+='#'; while(blank(ch) ) {ch=gc();} while(!blank(ch) ) {s+=ch;ch=gc();} } inline void ps(char *s){ while(*s!=0) pc(*s++); } inline void ps(const std::string &s){ for(auto it:s) if(it!='#') pc(it); } template<class T> inline void read(T &s){ s=0;char ch=gc();bool f=0; while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();} while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();} if(ch=='.'){ db p=0.1;ch=gc(); while('0'<=ch&&ch<='9') {s=s+p*(ch^48);p*=0.1;ch=gc();} } s=f?-s:s; } template<class T,class ...A> inline void read(T &s,A &...a){ read(s);read(a...); } }; using IO::read; using IO::gs; using IO::ps; const int N=1e7+3; int n; struct node{ int w,k; int lc,rc; }t[N]; int stk[N],top; inline void build(){ top=0; for(int i=1;i<=n;++i){ int k=top; while(k and t[stk[k] ].w>t[i].w) --k; if(k) t[stk[k] ].rc=i; if(k<top) t[i].lc=stk[k+1]; stk[++k]=i; top=k; } } int main(){ //filein(a);fileot(a); read(n); for(int i=1;i<=n;++i){ read(t[i].w); t[i].k=i; } build(); ll ans1=0,ans2=0; for(int i=1;i<=n;++i){ ans1^=1ll*i*(t[i].lc+1); ans2^=1ll*i*(t[i].rc+1); } printf("%lld %lld\n",ans1,ans2); return 0; }