[线段树模拟Treap]Codechef COT5 .Count on a Treap
2017-09-25 17:00
519 查看
很早以前留下的坑了
首先把所有点按key排序,那么这个序列就是Treap的中序遍历了。
很显然两个点之间的weight最大的点是它们的LCA
那么根据 ans=depthx+depthy−2∗depthlca
只要能算出 depthx 就行了。
画画图可以知道这个值就是这个点往两边的上升序列长度之和,可以用BZOJ2957的做法,用线段树搞。
复杂度 O(nlog2n)
首先把所有点按key排序,那么这个序列就是Treap的中序遍历了。
很显然两个点之间的weight最大的点是它们的LCA
那么根据 ans=depthx+depthy−2∗depthlca
只要能算出 depthx 就行了。
画画图可以知道这个值就是这个点往两边的上升序列长度之和,可以用BZOJ2957的做法,用线段树搞。
复杂度 O(nlog2n)
#include <cstdio> #include <iostream> #include <algorithm> #define fi first #define se second using namespace std; typedef unsigned int ll; typedef pair<ll,int> PAR; const int N=400010; int n; int l ,cnt; struct Qry{ int opt,x,k; }Q ; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void rea(ll &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); } inline void rea(int &x){ char c=nc(); x=0; for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc()); } int v[N<<1]; int vl[N<<2],vr[N<<2],mx[N<<2],mxp[N<<2]; int Queryl(int g,int l,int r,int x){ if(x>mx[g]) return 0; if(l==r) return 1; int mid=l+r>>1; if(x>mx[g<<1|1]) return Queryl(g<<1,l,mid,x); else return vl[g<<1]+Queryl(g<<1|1,mid+1,r,x); } int Queryr(int g,int l,int r,int x){ if(x>mx[g]) return 0; if(l==r) return 1; int mid=l+r>>1; if(x>mx[g<<1]) return Queryr(g<<1|1,mid+1,r,x); else return Queryr(g<<1,l,mid,x)+vr[g<<1|1]; } inline void Up(int g,int l,int r){ mx[g]=mx[g<<1]; mxp[g]=mxp[g<<1]; if(mx[g<<1|1]>mx[g]) mx[g]=mx[g<<1|1],mxp[g]=mxp[g<<1|1]; int mid=l+r>>1; vl[g<<1]=Queryl(g<<1,l,mid,mx[g<<1|1]); vr[g<<1|1]=Queryr(g<<1|1,mid+1,r,mx[g<<1]); } void Add(int g,int l,int r,int x,int y){ if(l==r) return vl[g]=vr[g]=1,mx[g]=y,mxp[g]=l,void(); int mid=l+r>>1; if(x<=mid) Add(g<<1,l,mid,x,y); else Add(g<<1|1,mid+1,r,x,y); Up(g,l,r); } void Dlet(int g,int l,int r,int x){ if(l==r) return vl[g]=vr[g]=0,mx[g]=0,void(); int mid=l+r>>1; if(x<=mid) Dlet(g<<1,l,mid,x); else Dlet(g<<1|1,mid+1,r,x); Up(g,l,r); } PAR QueryMX(int g,int l,int r,int L,int R){ if(l==L && r==R) return PAR(mx[g],mxp[g]); int mid=l+r>>1; if(R<=mid) return QueryMX(g<<1,l,mid,L,R); else if(L>mid) return QueryMX(g<<1|1,mid+1,r,L,R); else{ PAR A=QueryMX(g<<1,l,mid,L,mid),B=QueryMX(g<<1|1,mid+1,r,mid+1,R); return A>B?A:B; } } PAR QueryL(int g,int L,int R,int l,int r,int x){ if(L==l && r==R) return PAR(Queryl(g,l,r,x),max(mx[g],x)); int mid=L+R>>1; if(r<=mid) return QueryL(g<<1,L,mid,l,r,x); else if(l>mid) return QueryL(g<<1|1,mid+1,R,l,r,x); else{ PAR A=QueryL(g<<1|1,mid+1,R,mid+1,r,x); PAR B=QueryL(g<<1,L,mid,l,mid,A.se); return PAR(A.fi+B.fi,max(A.se,B.se)); } } PAR QueryR(int g,int L,int R,int l,int r,int x){ if(L==l && r==R) return PAR(Queryr(g,l,r,x),max(mx[g],x)); int mid=L+R>>1; if(r<=mid) return QueryR(g<<1,L,mid,l,r,x); else if(l>mid) return QueryR(g<<1|1,mid+1,R,l,r,x); else{ PAR A=QueryR(g<<1,L,mid,l,mid,x); PAR B=QueryR(g<<1|1,mid+1,R,mid+1,r,A.se); return PAR(A.fi+B.fi,max(A.se,B.se)); } } inline int Dep(int x){ int ret=0; if(x>1) ret+=QueryL(1,1,cnt,1,x-1,v[x]).fi; if(x<cnt) ret+=QueryR(1,1,cnt,x+1,cnt,v[x]).fi; return ret; } int main(){ rea(n); for(int i=1;i<=n;i++){ rea(Q[i].opt); if(Q[i].opt==0) rea(Q[i].x),rea(Q[i].k),l[++cnt]=Q[i].x; else if(Q[i].opt==1) rea(Q[i].x),l[++cnt]=Q[i].x; else rea(Q[i].x),rea(Q[i].k),l[++cnt]=Q[i].x,l[++cnt]=Q[i].k; } sort(l+1,l+1+cnt); cnt=unique(l+1,l+1+cnt)-l-1; for(int i=1;i<=n;i++){ if(Q[i].opt==0) Q[i].x=lower_bound(l+1,l+1+cnt,Q[i].x)-l; else if(Q[i].opt==1) Q[i].x=lower_bound(l+1,l+1+cnt,Q[i].x)-l; else Q[i].x=lower_bound(l+1,l+1+cnt,Q[i].x)-l,Q[i].k=lower_bound(l+1,l+1+cnt,Q[i].k)-l; } for(int i=1;i<=n;i++){ if(Q[i].opt==0) Add(1,1,cnt,Q[i].x,Q[i].k),v[Q[i].x]=Q[i].k; else if(Q[i].opt==1) Dlet(1,1,cnt,Q[i].x); else{ if(Q[i].x>Q[i].k) swap(Q[i].x,Q[i].k); int LCA=QueryMX(1,1,cnt,Q[i].x,Q[i].k).se; printf("%d\n",Dep(Q[i].x)+Dep(Q[i].k)-2*Dep(LCA)); } } return 0; }
相关文章推荐
- [Treap模拟 线段树] Codechef COT5 Count on a Treap
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
- 【线段树,Treap】CodeChef COT5 Count on a Treap
- 2588: Spoj 10628. Count on a tree[可持久化线段树+倍增lca]
- BZOJ 2588 Count on a tree (COT) 可持久化线段树
- 【bzoj 2588】Count on a tree(可持久化线段树+LCA)
- 【可持久化线段树】[SPOJ COT]Count on a tree
- 【BZOJ2588】【Spoj 10628.】 Count on a tree 可持久化线段树+lca
- SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)
- hdu 2665 Kth number (函数式线段树)+ SPOJ Count on a tree
- 【spoj】【COT - Count on a tree】【可持久化线段树】
- HDU 4942 Game on S♂play(线段树、模拟、扩栈)
- [Splay模拟 线段树 || Splay || LCT] HDU 4942 Game on S♂play
- [bzoj 2588] Spoj 10628. Count on a tree:函数式线段树
- 2588: Spoj 10628. Count on a tree (可持久化线段树)
- [BZOJ2588]Count on a tree(可持久化权值线段树|主席树)
- bzoj2588:Count on a tree(可持久化线段树+Lca)
- HDU 4302 Holedox Eating (线段树模拟)
- [spoj10707]Count on a tree II 解题报告
- 存储过程里的'set nocount on'是什么意思?