笛卡尔树
作者:互联网
笛卡尔树
定义
同时满足堆和二叉搜索树的性质。即对于每个节点有两个键值 \(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;
}
标签:ch,笛卡尔,void,while,gc,inline,define 来源: https://www.cnblogs.com/cbdsopa/p/16135939.html