社区讨论
悲伤的树剖,怎么都是TLE三个点 不变的蓝色 求看
P3384【模板】重链剖分 / 树链剖分参与者 2已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mi6vptf5
- 此快照首次捕获于
- 2025/11/20 11:36 4 个月前
- 此快照最后确认于
- 2025/11/20 11:36 4 个月前
别人的代码跑500ms,我的跑5000ms,然而并没有什么差别的样子
巨丑无比而且还不停加玄学优化的代码:
(已经调试两天了,悲伤)
CPP#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
#include<map>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<set>
#include<cstring>
#define mid ((l+r)>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define Rint register int
#define lf k<<1
#define ri k<<1|1
#define late c_l,c_r
using namespace std;
typedef long long ll;
const ll INF=99999999;
const int MAXN=200010;
long long n,m,r,mod;
int ecnt,head[MAXN],nxt[MAXN],to[MAXN];
int w[MAXN],wt[MAXN];
long long tree[MAXN<<2],lazy[MAXN<<2];
int heavy[MAXN],dfn[MAXN],father[MAXN],DFS_cnt;
int deep[MAXN],Size[MAXN],Top[MAXN];
long long res;
void DFS_1(int now,int fa){
deep[now]=deep[fa]+1;
father[now]=fa;
Size[now]=1;
for(Rint i=head[now];i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
DFS_1(v,now);
Size[now]+=Size[v];
if(heavy[now]==0||Size[v]>heavy[now]) heavy[now]=v;
}
}
void DFS_2(int now,int nowTop){
dfn[now]=++DFS_cnt;
wt[DFS_cnt]=w[now];
Top[now]=nowTop;
if(!heavy[now]) return;
DFS_2(heavy[now],nowTop);
for(Rint i=head[now];i;i=nxt[i]){
int v=to[i];
if(v==father[now]||v==heavy[now]) continue;
DFS_2(v,v);
}
}
void add(int frm,int to_){
to[++ecnt]=to_;
nxt[ecnt]=head[frm];
head[frm]=ecnt;
}
void pushdown(int k,int lenn){
lazy[k<<1]+=lazy[k];
lazy[k<<1|1]+=lazy[k];
tree[k<<1]+=lazy[k]*(lenn-(lenn>>1));
tree[k<<1|1]+=lazy[k]*(lenn>>1);
tree[k<<1]%=mod;
tree[k<<1|1]%=mod;
lazy[k]=0;
}
void build(int k,int l,int r)
{
if(l==r){
tree[k]=wt[l];
if(tree[k]>mod) tree[k]%=mod;
return;
}
build(lson);
build(rson);
tree[k]=(tree[lf]+tree[ri])%mod;
}
void query(int k,int l,int r,int c_l,int c_r){
if(l>=c_l&&r<=c_r)
{
res+=tree[k];
res%=mod;
return;
}
if(lazy[k])
pushdown(k,r-l+1);
if(c_l<=mid) query(lson,late);
if(c_r>mid) query(rson,late);
}
void addRange(int k,int l,int r,int x,int c_l,int c_r){
if(l>=c_l&&r<=c_r){
lazy[k]+=x;
tree[k]+=x*(r-l+1);
}
else{
if(lazy[k])
pushdown(k,r-l+1);
if(c_l<=mid) addRange(lson,x,late);
if(c_r>mid) addRange(rson,x,late);
tree[k]=(tree[lf]+tree[ri])%mod;
}
}
int getRange(int u,int v)
{
int re=0;
while(Top[u]!=Top[v]){
if(deep[Top[u]]<deep[Top[v]]) swap(u,v);
res=0;
query(1,1,n,dfn[Top[u]],dfn[u]);
//cout<<"add:"<<res<<" to:"<<father[Top[u]]<<endl;
re+=res;
re%=mod;
u=father[Top[u]];
}
if(deep[u]>deep[v]) swap(u,v);
res=0;
query(1,1,n,dfn[u],dfn[v]);
re+=res;
return re%mod;
}
void updRange(int u,int v,int x){
x%=mod;
while(Top[u]!=Top[v]){
if(deep[Top[u]]<deep[Top[v]]) swap(u,v);
addRange(1,1,n,x,dfn[Top[u]],dfn[u]);
u=father[Top[u]];
}
if(deep[u]>deep[v]) swap(u,v);
addRange(1,1,n,x,dfn[u],dfn[v]);
}
int getSonTree(int l){
res=0;
query(1,1,n,dfn[l],dfn[l]+Size[l]-1);
return res;
}
void updSonTree(int l,int x){
addRange(1,1,n,x,dfn[l],dfn[l]+Size[l]-1);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>r>>mod;
for(Rint i=1;i<=n;i++){
cin>>w[i];
}
for(Rint i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
DFS_1(r,0);
DFS_2(r,r);
build(1,1,n);
for(Rint J=1;J<=m;J++){
int a,b,c,d;
cin>>a>>b;
if(a==1){
cin>>c>>d;
updRange(b,c,d);
}
else if(a==2){
cin>>c;
cout<<getRange(b,c)%mod<<endl;
}
else if(a==3){
cin>>c;
updSonTree(b,c);
}
else{
cout<<getSonTree(b)%mod<<endl;
}
}
return 0;
}
回复
共 3 条回复,欢迎继续交流。
正在加载回复...