1. 程式人生 > 資訊 >京東:第五代無人智慧快遞車在上海開展無接觸配送,首批超 8 萬件母嬰物資緊急運達

京東:第五代無人智慧快遞車在上海開展無接觸配送,首批超 8 萬件母嬰物資緊急運達

笛卡爾樹

定義

同時滿足堆和二叉搜尋樹的性質。即對於每個節點有兩個鍵值 \(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;
}