社区讨论

求助常数

P3241[HNOI2015] 开店参与者 1已保存回复 1

讨论操作

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

当前回复
1 条
当前快照
1 份
快照标识符
@lo9b42fi
此快照首次捕获于
2023/10/28 08:31
2 年前
此快照最后确认于
2023/10/28 08:31
2 年前
查看原帖
本人处理询问的代码如下:
CPP
struct Vec
{//age:当前点的妖怪年龄 s1:子树内<=age点到自己的距离和 s2:子树内<=age点到父亲的距离和 
	int num,s1,s2;
	Vec( int N=0 , int S1=0 , int S2=0 ) { num=N,s1=S1,s2=S2; }
};
inline int qget( vector<Vec> a , int k )
{//二分得到点分树所有权值<=k点集合
	int l=0,r=a.size()-1,ret=-1;
	while( l<=r )
	{
		int mid=(l+r)>>1;
		if( age[a[mid].num]<=k )
			ret=mid,l=mid+1;
		else r=mid-1;
	}
	return ret;
}
inline int dist( int x , int y )
{//O(1)lca_dist
	int ret=depth[x]+depth[y];
	x=bac[x],y=bac[y];
	if( x>y ) swap(x,y);
	int tep=0;while( 1<<(tep+1)<=y-x+1 ) ++tep;
	return ret-2*min(depth[st[x][tep]],depth[st[y-(1<<tep)+1][tep]]);
}
inline int query( int x , int k )
{//age<=k的点距离x位置集合 
	int p=qget(a[x],k),lasp,ret=0;
	if( p!=-1 ) ret=a[x][p].s1;
	for(int u=x;fa_dop[u];u=fa_dop[u])
	{//在点分树上跳父亲
		lasp=p;
		p=qget(a[fa_dop[u]],k);
		if( p==-1 ) continue;
		else if( lasp==-1 ) ret+=a[fa_dop[u]][p].s1+dist(x,fa_dop[u])*(p+1);
		else ret+=a[fa_dop[u]][p].s1-a[u][lasp].s2+dist(x,fa_dop[u])*(p-lasp);
	}
	return ret;
}
inline void solve()
{
	for(int i=1,u,l,r;i<=m;i++)
	{//处理询问
		read(u),read(l),read(r);
        	...
		las_ans=(query(u,r)-query(u,l-1));
		printf("%d\n",las_ans);
	}
}
预处理点分树可以做到2s以内,但询问跑出了900ms(q=100)、8000ms(q=1000)、19500ms(q=2000)的好成绩。 初步认为是询问常数过大。是因为在vector里二分的原因吗?求教orz

回复

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

正在加载回复...