首页 > 其他分享 >[loj3832]无线电信号塔

[loj3832]无线电信号塔

时间:2023-01-20 10:35:42浏览次数:39  
标签:dep return sub int 无线电 fa 信号 -- loj3832

为了方便,这里将下标均\(+1\),并在\(0\)和\(n+1\)处建立无穷高的塔

记\(i\)左右两侧第一个\(\ge h_{i}+\delta\)的塔为\(l_{i}\)和\(r_{i}\),则通信条件也即\(r_{i}<j\)且\(l_{j}>i\)

将条件转换到塔上,即集合\(S\)合法当且仅当\(\forall i\in S,S\cap (l_{i},r_{i})=\empty\)

(本来应该是\([l_{i},r_{i}]\),但如果选了\(l_{i}\)或\(r_{i}\),则对于所选塔仍不合法)

不妨假设\(h_{l_{i}}<h_{r_{i}}\),则\((l_{i},r_{i})\)即为笛卡尔树上\(l_{i}\)右儿子的子树(反之同理)

记\(z_{i}\)为\((l_{i},r_{i})\)对应子树的根,则限制等价于\(\forall i\in S,z_{i}\)两两(不同且)不成祖先-后代关系

显然可以贪心选极深的\(z_{i}\),即统计节点\(k\)满足\(\min_{i\in sub_{k}\cap [L,R]}h_{i}\in (h_{k}-\delta,h_{fa_{k}}-\delta]\)

  • 对于\(L,R\not\in sub_{k}\),容斥为全体\(-[l_{k}\le L]-[R\le r_{k}]+[[L,R]\subseteq sub_{k}]\)

    前三类均可用主席树维护,第\(4\)类即\(lca(L,R)\)的祖先,在树上维护主席树即可

  • 对于\(L\)或\(R\in sub_{k}\),即\(L\)或\(R\)的祖先,根据单调性倍增+ST表维护即可

时间复杂度为\(O(n\log n+q\log n)\)

#include<bits/stdc++.h>
#include "towers.h"
using namespace std;
#define mid (l+r>>1)
const int N=100005,M=20000000;
int n,rt,ans,h[N],st[N],ls[M],rs[M];
int fa[N][20],dep[N],l[N],r[N],mn[N];
int V,lg[N],ST[N][20],rtl[N],rtr[N],rtt[N],f[M];
vector<int>vl[N],vr[N];
int Cpy(int k){
	ls[++V]=ls[k],rs[V]=rs[k],f[V]=f[k];
	return V;
}
void update(int &k,int l,int r,int x,int y){
	k=Cpy(k),f[k]+=y;
	if (l==r)return;
	if (x<=mid)update(ls[k],l,mid,x,y);
	else update(rs[k],mid+1,r,x,y);
} 
int query(int k,int l,int r,int x,int y){
	if ((!k)||(l>y)||(x>r))return 0;
	if ((x<=l)&&(r<=y))return f[k];
	return query(ls[k],l,mid,x,y)+query(rs[k],mid+1,r,x,y);
}
int query(int l,int r){
	int m=lg[r-l+1];
	return min(ST[l][m],ST[r-(1<<m)+1][m]);
}
int lca(int x,int y){
	if (dep[x]<dep[y])swap(x,y);
	for(int i=19;i>=0;i--)
		if (dep[fa[x][i]]>=dep[y])x=fa[x][i];
	if (x==y)return x;
	for(int i=19;i>=0;i--)
		if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
void dfs(int k,int f,int s){
	if (!k)return;
	fa[k][0]=f,dep[k]=s;
	for(int i=1;i<20;i++)fa[k][i]=fa[fa[k][i-1]][i-1];
	dfs(ls[k],k,s+1),dfs(rs[k],k,s+1);
	l[k]=(ls[k] ? l[ls[k]] : k);
	r[k]=(rs[k] ? r[rs[k]] : k);
	mn[k]=min(min(mn[ls[k]],mn[rs[k]]),h[k]);
	vl[l[k]].push_back(k),vr[r[k]].push_back(k);
}
void Dfs(int k){
	if (!k)return;
	rtt[k]=rtt[fa[k][0]];
	update(rtt[k],1,1e9,h[k]-mn[k]+1,1);
	if (k!=rt)update(rtt[k],1,1e9,h[fa[k][0]]-mn[k]+1,-1);
	Dfs(ls[k]),Dfs(rs[k]);
}
void init(int _n,vector<int>_h){
	n=_n;
	for(int i=0;i<n;i++)h[i+1]=_h[i];
	for(int i=1;i<=n;i++){
		int lst=0;
		while ((st[0])&&(h[st[st[0]]]<h[i])){
			rs[st[st[0]]]=lst;
			lst=st[st[0]--];
		}
		ls[i]=lst,st[++st[0]]=i;
	}
	int lst=0;
	while (st[0]){
		rs[st[st[0]]]=lst;
		lst=st[st[0]--];
	}
	rt=lst,mn[0]=1e9,dfs(rt,0,1);
	lg[0]=-1;
	for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
	for(int i=n;i;i--){
		ST[i][0]=h[i];
		for(int j=1;j<20;j++)ST[i][j]=min(ST[i][j-1],ST[min(i+(1<<j-1),n)][j-1]);
	}
	V=n;
	for(int i=1;i<=n;i++){
		rtl[i]=rtl[i-1],rtr[i]=rtr[i-1];
		for(int j:vl[i]){
			update(rtl[i],1,1e9,h[j]-mn[j]+1,1);
			if (j!=rt)update(rtl[i],1,1e9,h[fa[j][0]]-mn[j]+1,-1);
		}
		for(int j:vr[i]){
			update(rtr[i],1,1e9,h[j]-mn[j]+1,1);
			if (j!=rt)update(rtr[i],1,1e9,h[fa[j][0]]-mn[j]+1,-1);
		}
	}
	Dfs(rt);
}
int max_towers(int L,int R,int D){
	L++,R++;
	int k=lca(L,R);
	if (h[k]-D<query(L,R))return 1;
	ans=query(rtr[R-1],1,1e9,1,D)-query(rtl[L],1,1e9,1,D)+query(rtt[k],1,1e9,1,D);
	if (h[L]-D<query(L,r[L])){
		k=L;
		for(int i=19;i>=0;i--)
			if ((fa[k][i])&&(h[fa[k][i]]-D<query(L,r[fa[k][i]])))k=fa[k][i];
		if (query(L,r[k])<=h[fa[k][0]]-D)ans++;
	}
	if (h[R]-D<query(l[R],R)){
		k=R;
		for(int i=19;i>=0;i--)
			if ((fa[k][i])&&(h[fa[k][i]]-D<query(l[fa[k][i]],R)))k=fa[k][i];
		if (query(l[k],R)<=h[fa[k][0]]-D)ans++;
	}
	return ans;
}

标签:dep,return,sub,int,无线电,fa,信号,--,loj3832
From: https://www.cnblogs.com/PYWBKTDA/p/17062475.html

相关文章