社区讨论
求助常数
P3241[HNOI2015] 开店参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lo9b42fi
- 此快照首次捕获于
- 2023/10/28 08:31 2 年前
- 此快照最后确认于
- 2023/10/28 08:31 2 年前
本人处理询问的代码如下:
CPPstruct 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 条回复,欢迎继续交流。
正在加载回复...