求证复杂度
查看原帖
求证复杂度
366171
DerrickLo楼主2023/11/22 19:03

rt,用了一个不清楚复杂度的线段树做法,大概是线段树每个节点除了维护最小值还维护区间内深度最小值和深度最大值,如果深度最小值过大则不用判断,如果这个区间被包含且深度最大值不大时直接统计答案,其他情况分两个区间,请问复杂度为什么正确/yiw

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,r,a[100005],u,v,m,p,q,id[100005],dep[100005],cnt,nw[100005],last,sz[100005];
vector<int> ve[100005];
struct tree{
	int l,r,maxx,minx,minn;
}tr[400005];
void pushup(int u){
	tr[u].maxx=max(tr[u<<1].maxx,tr[u<<1|1].maxx);
	tr[u].minx=min(tr[u<<1].minx,tr[u<<1|1].minx);
	tr[u].minn=min(tr[u<<1].minn,tr[u<<1|1].minn);
}
void dfs(int u,int fa){
	id[u]=++cnt,dep[u]=dep[fa]+1,nw[id[u]]=u,sz[u]=1;
	for(int v:ve[u]){
		if(v==fa)continue;
		dfs(v,u);
		sz[u]+=sz[v];
	}
}
void build(int u,int l,int r){
	if(l==r){
		tr[u]={l,r,dep[nw[l]],dep[nw[l]],a[nw[l]]};
		return;
	}
	tr[u]={l,r};
	int mid=l+r>>1;
	build(u<<1,l,mid),build(u<<1|1,mid+1,r);
	pushup(u);
}
int query(int u,int l,int r,int k){
	if(tr[u].l>r||tr[u].r<l)return LONG_LONG_MAX;
	if(tr[u].minx>k)return LONG_LONG_MAX;//最小值过大
	if(tr[u].l>=l&&tr[u].r<=r&&tr[u].maxx<=k)return tr[u].minn;//完全包含且最大值不大
	int mid=tr[u].l+tr[u].r>>1,res=LONG_LONG_MAX;
	if(l<=mid)res=min(res,query(u<<1,l,r,k));
	if(r>mid)res=min(res,query(u<<1|1,l,r,k));
	return res;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>r;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<n;i++)cin>>u>>v,ve[u].emplace_back(v),ve[v].emplace_back(u);
	dfs(r,-1);
	build(1,1,n);
	cin>>m;
	while(m--){
		cin>>p>>q;
		int x=(p+last)%n+1,k=(q+last)%n;
		int ans=query(1,id[x],id[x]+sz[x]-1,dep[x]+k);
		cout<<ans<<"\n",last=ans;
	}
	return 0;
}
2023/11/22 19:03
加载中...