1. 程式人生 > 其它 >第一章 MySQL體系結構和儲存引擎(學習筆記)

第一章 MySQL體系結構和儲存引擎(學習筆記)

題面傳送門
不得不說這個正解是真的暴力本來還想寫可持久化平衡樹的(
考慮我們將每個新加入的樹看作一個點。
那麼我們要支援這些操作:
查詢一個點在那個樹裡面,這個直接lowerbound就好了。
查詢一顆樹內某個點在原樹哪個節點,這個直接把原樹的dfs序拍瞭然後主席樹區間\(k\)大就好了。
查詢現在樹上兩個同一棵樹的節點距離,這個直接找到在原樹上哪個節點然後倍增就好了。
那麼在中間新樹上倍增,兩端和lca處到原樹上倍增就好了。
時間複雜度大常數\(O(nlogn)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 100000
#define mod 998244353
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,Q,lg[N+5],bg[N+5],siz[N+5],Fr[N+5];ll x,y,z,st[N+5],en[N+5];
struct yyy{int to,z;};I void swap(int &x,int &y){x^=y^=x^=y;}
struct ljb{int head,h[N+5];yyy f[N+5<<1];I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}};
struct Tree1{
	ljb s;int fa[N+5][20],root[N+5],d[N+5],dfn[N+5],dh,L[N+5<<5],R[N+5<<5],F[N+5<<5],cnt;
	I void memcpy(int x,int y){R[y]=R[x];L[y]=L[x];F[y]=F[x];}
	I void insert(int x,int &now,int l=1,int r=n){memcpy(now,++cnt);now=cnt;F[now]++;if(l==r) return;int m=l+r>>1;x<=m?insert(x,L[now],l,m):insert(x,R[now],m+1,r);}
	I int Query(int x,int y,int z,int l=1,int r=n){int m;x=root[x-1];y=root[y];while(l^r) m=l+r>>1,z<=F[L[y]]-F[L[x]]?(y=L[y],x=L[x],r=m):(z-=F[L[y]]-F[L[x]],y=R[y],x=R[x],l=m+1);return l;}
	I void dfs(int x,int last){dfn[bg[x]=++dh]=x;siz[x]=1;d[x]=d[last]+1;fa[x][0]=last;int i;yyy tmp;for(i=1;fa[x][i-1];i++) fa[x][i]=fa[fa[x][i-1]][i-1];for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(dfs(tmp.to,x),siz[x]+=siz[tmp.to]);}
	I int dist(int x,int y){d[x]<d[y]&&(swap(x,y),0);int Ans=d[x]-d[y];while(d[x]^d[y]) x=fa[x][lg[d[x]-d[y]]];if(x==y) return Ans;for(int i=lg[d[x]];~i;i--) fa[x][i]&&fa[y][i]&&fa[x][i]^fa[y][i]&&(x=fa[x][i],y=fa[y][i],Ans+=2<<i);return Ans+2;}
	I void Make(){re int i;for(i=1;i<n;i++) scanf("%lld%lld",&x,&y),s.add(x,y),s.add(y,x);dfs(1,0);for(i=1;i<=n;i++) root[i]=root[i-1],insert(dfn[i],root[i]);}
	I int FindId(ll x,int id){return Query(bg[Fr[id]],bg[Fr[id]]+siz[Fr[id]]-1,x-st[id]+1);}
}T1;
struct Tree2{
	int fa[N+5][20],d[N+5],nx,ny,lcas;ll cnt,To[N+5],W[N+5];ljb s;
	I void dfs(int x,int last){yyy tmp;int i;d[x]=d[last]+1;W[x]+=W[last];for(i=1;fa[x][i-1];i++) fa[x][i]=fa[fa[x][i-1]][i-1];for(i=s.h[x];i;i=tmp.z) tmp=s.f[i],dfs(tmp.to,x);}
	I int lca(int x,int y){d[x]<d[y]&&(swap(x,y),0);while(d[x]^d[y]) x=fa[x][lg[d[x]-d[y]]];if(x==y) return x;for(int i=lg[d[x]];~i;i--) fa[x][i]&&fa[y][i]&&fa[x][i]^fa[y][i]&&(x=fa[x][i],y=fa[y][i]);return fa[x][0];}
	I int kth(int x,int k){while(k) x=fa[x][lg[k&-k]],k-=k&-k;return x;}
	I ll dist(ll x,ll y){
		nx=lower_bound(en+1,en+m,x)-en;ny=lower_bound(en+1,en+m,y)-en;d[nx]<d[ny]&&(swap(nx,ny),swap(x,y),0);lcas=lca(nx,ny);if(nx==ny) return T1.dist(T1.FindId(x,nx),T1.FindId(y,ny));ll Ans=0;
		if(lcas==ny){Ans=T1.dist(Fr[nx],T1.FindId(x,nx))+1+W[nx];x=kth(nx,d[nx]-d[lcas]-1);Ans-=W[x];return Ans+dist(T1.FindId(To[x],ny),T1.FindId(y,ny));}
		Ans=T1.dist(Fr[nx],T1.FindId(x,nx))+T1.dist(Fr[ny],T1.FindId(y,ny))+2+W[nx]+W[ny];x=kth(nx,d[nx]-d[lcas]-1);y=kth(ny,d[ny]-d[lcas]-1);Ans-=W[x]+W[y];return Ans+T1.dist(T1.FindId(To[x],lcas),T1.FindId(To[y],lcas));
	}
	I void Make(){
		re int i;st[1]=1;cnt=en[1]=n;Fr[1]=1;m++;for(i=2;i<=m;i++) scanf("%d%lld",&Fr[i],&To[i]),st[i]=cnt+1,cnt+=siz[Fr[i]],en[i]=cnt,fa[i][0]=z=lower_bound(en+1,en+i,To[i])-en,s.add(z,i),W[i]=T1.dist(Fr[z],T1.FindId(To[i],z))+1;
		dfs(1,0);while(Q--) scanf("%lld%lld",&x,&y),printf("%lld\n",dist(x,y));
	}
}T2;
int main(){
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
	re int i;scanf("%d%d%d",&n,&m,&Q);for(i=2;i<=max(n,m);i++)lg[i]=lg[i/2]+1;T1.Make();T2.Make();
}