社区讨论

第三个样例一直过不了,求调,cdq分治做法

P11364[NOIP2024] 树上查询参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@miihp1u2
此快照首次捕获于
2025/11/28 14:36
3 个月前
此快照最后确认于
2025/11/29 14:45
3 个月前
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
int q,n,head[500005],tot,cnt,dep[500005],f[500005],st[500005][25],st1[500005][25],dfn[500005],id[500005],num,c[500005],r[500005],ans[500005],b[500005];
struct sd{
	int ne,to;
}edge[1000005];
struct sp{
	int l,r,len,id,v;
}a[1000005];
void add(int x,int y){
	edge[++tot].ne=head[x];
	edge[tot].to=y;
	head[x]=tot;
} 
void dfs(int x,int fa){
	dep[x]=dep[fa]+1;
//	printf("%d %d\n",x,dep[x]);
	dfn[x]=++num;
	f[x]=fa;
	id[num]=x;
	for(int i=head[x];i;i=edge[i].ne){
		int y=edge[i].to;
		if(y==fa)	continue;
		dfs(y,x);
	}
	r[x]=num;
}
int get(int x,int y){
	if(dep[x]<dep[y])	return x;
	return y;
}
void pre(){
	for(int i=1;i<=num;i++)	st[i][0]=id[i];
	int t=log(num)/log(2)+1;
	for(int j=1;j<=t;j++){
		for(int i=1;i<=num-(1<<j)+1;i++){
			st[i][j]=get(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
	for(int i=1;i<=n;i++)	st1[i][0]=dep[i];
	t=log(n)/log(2)+1;
	for(int j=1;j<=t;j++){
		for(int i=1;i<=n-(1<<j)+1;i++){
			st1[i][j]=max(st1[i][j-1],st1[i+(1<<(j-1))][j-1]);
		}
	}
}
int getlca(int x,int y){
	if(dfn[x]>dfn[y])	swap(x,y);
	if(r[x]>=r[y])	return x;
	int t=log(dfn[y]-dfn[x]+1)/log(2);
	return f[get(st[dfn[x]][t],st[dfn[y]-(1<<t)+1][t])];
}
int lowbit(int x){
	return x&(-x);
}
void add1(int x,int v){
	if(!x)	return ;
	for(;x;x-=lowbit(x))	c[x]=max(c[x],v);
}
int ask(int x){
	if(!x)	return 0; 
	int res=0;
	for(;x<=n;x+=lowbit(x))	res=max(res,c[x]);
	return res;
}
void del(int x){
	if(!x)	return ;
	for(;x;x-=lowbit(x))	c[x]=0;
}
bool cmp(sp x,sp y){
	if(x.l==y.l && x.r==y.r)	return x.len>y.len; 
	if(x.l==y.l)	return x.r>y.r;
	return x.l>y.l;
}
bool cmp1(sp x,sp y){
	if(x.r==y.r)	return x.len>y.len; 
	return x.r>y.r;
}
void cdq(int l,int r){
	if(l>=r)	return ;
	int mid=(l+r)>>1;
	cdq(l,mid),cdq(mid+1,r);
	int ll=l,rr=mid+1;
	for(;rr<=r;rr++){
		while(ll<=mid && a[ll].r>=a[rr].r){
			if(!a[ll].id)add1(a[ll].len,a[ll].v);
			ll++;
		}
		if(a[rr].id)ans[a[rr].id]=max(ans[a[rr].id],ask(a[rr].len));
//		printf("%d %d\n",rr,r);
//		printf("%d ",ll);
	}
//	printf("%d ",rr);
	for(int i=l;i<ll;i++){
		if(!a[i].id)	del(a[i].len);
	}
	sort(a+l,a+r+1,cmp1);
//	printf("%d %d\n",l,r);
//	for(int i=1;i<=q;i++)	printf("%d ",ans[i]);
//	printf("\n");
}
int rmq(int l,int r){
	int t=log(r-l+1)/log(2);
	return max(st1[l][t],st1[r-(1<<t)+1][t]);
}
int main(){
//	freopen("query3.in","r",stdin);
//	freopen("query.out","w",stdout); 
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	dfs(1,0);
	pre();
	for(int i=1;i<n;i++)	b[i]=getlca(i,i+1);//,printf("%d ",b[i]);
	stack<int>	stk;
	stk.push(0);
	for(int i=1;i<n;i++){
		while(stk.size() && dep[b[stk.top()]]>=dep[b[i]])	stk.pop();
		a[i].l=-stk.top()-1;
		stk.push(i);
	}
	while(stk.size())	stk.pop();
	stk.push(n);
	for(int i=n-1;i>=1;i--){
		while(stk.size() && dep[b[stk.top()]]>=dep[b[i]])	stk.pop();
		a[i].r=stk.top();
		a[i].len=a[i].r+a[i].l;
		a[i].id=0;
		a[i].v=dep[b[i]];
		stk.push(i);
//		printf("%d %d %d %d\n",a[i].l,a[i].r,i,dep[i]);
	}
//	printf("1");
	scanf("%d",&q);
	cnt=n-1;
	for(int i=1;i<=q;i++){
		int l,r,k;
		scanf("%d%d%d",&l,&r,&k);
		if(k!=1)	a[++cnt]={k-r-1,l+k-1,k-1,i,0};
		else{
			if(l==r)	ans[i]=dep[l];
			else	ans[i]=rmq(l,r);
		}
	}
//	memset(ans,0x3f,sizeof(ans));
	sort(a+1,a+cnt+1,cmp);
//	for(int i=1;i<=cnt;i++){
//		printf("%d %d %d %d %d\n",a[i].l,a[i].r,a[i].len,a[i].id,a[i].v);
//	}
	cdq(1,cnt);
	for(int i=1;i<=q;i++)	printf("%d\n",ans[i]);
}

回复

3 条回复,欢迎继续交流。

正在加载回复...