[naval International Program Office] binary search tree

Posted by jmaker on Sun, 19 Dec 2021 14:25:34 +0100

Binary search tree

Problem solution

First of all, we find that for any subtree, the weight with you contained in it must be continuous to all our points added to the tree.
Therefore, if we connect two subtrees to one root in reverse, the value range of the connected root must also be continuous. We can consider the interval dp.
For points with fixed order, we can obviously directly know which subtrees are on both sides of it, and connect them directly.
For those points whose order is not fixed, we can only deal with them through interval dp.
But in fact, every time we d p dp dp must be a continuous segment, that is, our total d p dp dp will be used in total [ 1 , l ) [1,l) [1,l) the built tree is divided into several small segments. We need to perform interval dp for the interior of these small segments.
We might as well [ l , r ] [l,r] All the points in [l,r] are sorted by size, and d p l , r dp_{l,r} dpl,r , indicates that the value range is [ a l , a r ] [a_{l},a_{r}] The depth sum of the subtree formed by the points of [al, ar] is easy to obtain the transfer equation
d p l , r = max ⁡ m i d = l r d p l , m i d − 1 + d p m i d + r , r + r − l dp_{l,r}=\max_{mid=l}^{r}dp_{l,mid-1+dp_{mid+r,r}}+r-l dpl,r​=mid=lmaxr​dpl,mid−1+dpmid+r,r​​+r−l
But obviously this is not complete, because we need to consider the contribution of the later fixed points, that is, if the root of our American drama happens to be one of the left and right endpoints, we need to add the subtree size built by the fixed points on that side.
Find the interval d p dp After the dp value, we can choose any node as the root, and then continue to process the previous paragraph.
As for maintaining the root of the subtree where a node is located, we can use and query set for maintenance.

Time complexity O ( α ( n ) n + ( r − l ) 3 ) O\left(\alpha(n)n+(r-l)^3\right) O(α(n)n+(r−l)3).

Source code

#include<bits/stdc++.h> 
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int zero=10000;
const int lim=30000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,b[MAXN],fa[MAXN],L[MAXN],R[MAXN],l,r;LL dp[MAXN],g[405][405]; 
int findSet(int x){return fa[x]==x?x:fa[x]=findSet(fa[x]);}
signed main(){
	read(n);
	for(int i=1;i<=n;i++)read(b[i]);read(l);read(r);
	for(int i=n;i>r;i--){
		fa[b[i]]=b[i];L[b[i]]=b[i];R[b[i]]=b[i];dp[b[i]]=1;
		if(fa[b[i]-1]){
			int x=findSet(b[i]-1);L[b[i]]=L[x];
			dp[b[i]]+=dp[x]+1ll*(R[x]-L[x]+1);fa[x]=b[i];
		}
		if(fa[b[i]+1]){
			int x=findSet(b[i]+1);R[b[i]]=R[x];
			dp[b[i]]+=dp[x]+1ll*(R[x]-L[x]+1);fa[x]=b[i];
		}
	}
	sort(b+l,b+r+1);
	for(int i=l,j;i<=r;i=j+1){
		j=i;
		while(j<r){
			if(b[j+1]==b[j]+1){j++;continue;}
			if(!fa[b[j]+1]||!fa[b[j+1]-1])break;
			if(findSet(b[j]+1)==findSet(b[j+1]-1)){j++;continue;}
			break;
		}
		for(int len=1;len<=j-i+1;len++)
			for(int li=1,ri=len;ri<=j-i+1;li++,ri++){
				g[li][ri]=INF;
				for(int mid=li;mid<=ri;mid++){
					LL tmp=0;int lt=b[li+i-1]-1,rt=b[ri+i-1]+1;
					if(li==mid){if(fa[lt])tmp+=dp[findSet(lt)];}else tmp+=g[li][mid-1];
					if(ri==mid){if(fa[rt])tmp+=dp[findSet(rt)];}else tmp+=g[mid+1][ri];
					g[li][ri]=min(g[li][ri],tmp); 
				}
				int lt=fa[b[li+i-1]-1]?L[findSet(b[li+i-1]-1)]:b[li+i-1];
				int rt=fa[b[ri+i-1]+1]?R[findSet(b[ri+i-1]+1)]:b[ri+i-1];
				g[li][ri]+=1ll*(rt-lt+1);
			}
		for(int k=i;k<=j;k++){
			fa[b[k]]=b[k];L[b[k]]=b[k];R[b[k]]=b[k];
			if(fa[b[k]-1]){int x=findSet(b[k]-1);fa[x]=b[k];L[b[k]]=L[x];}
			if(fa[b[k]+1]){int x=findSet(b[k]+1);fa[x]=b[k];R[b[k]]=R[x];}
		}	
		dp[findSet(b[j])]=g[1][j-i+1];
	}
	for(int i=l-1;i>0;i--){
		fa[b[i]]=b[i];L[b[i]]=b[i];R[b[i]]=b[i];dp[b[i]]=1;
		if(fa[b[i]-1]){
			int x=findSet(b[i]-1);L[b[i]]=L[x];
			dp[b[i]]+=dp[x]+1ll*(R[x]-L[x]+1);fa[x]=b[i];
		}
		if(fa[b[i]+1]){
			int x=findSet(b[i]+1);R[b[i]]=R[x];
			dp[b[i]]+=dp[x]+1ll*(R[x]-L[x]+1);fa[x]=b[i];
		}
	}
	printf("%lld\n",dp[findSet(b[1])]);
	return 0;
}

thank you!!!

Topics: Dynamic Programming