社区讨论
10pts求助,玄关*2
P3384【模板】重链剖分 / 树链剖分参与者 2已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mhjuyrt0
- 此快照首次捕获于
- 2025/11/04 08:56 4 个月前
- 此快照最后确认于
- 2025/11/04 08:56 4 个月前
只AC了最后一个点
用测试点一数据自测,只对了第一次输出
CPP#include<bits/stdc++.h>
using namespace std;
# define int long long
const int N = 1e5+10;
// 建树
struct Edge
{
int to;
int Next;
}edge[N<<1];
int head[N+1];
int cnt=0;
int res,ans;
int n,m,r,MOD;
void add(int from, int to)
{
edge[++cnt].to = to;
edge[cnt].Next = head[from];
head[from] = cnt;
}
int fa[N],d[N],son[N],siz[N],top[N],w[N],nid[N],nw[N];
//树剖
void DFS1(int now,int dad)
{
fa[now] = dad;
siz[now] = 1;
son[now] = 0;
d[now] = d[dad] + 1;
for(int i = head[now]; i; i = edge[i].Next)
{
if(edge[i].to == dad)
continue;
DFS1(edge[i].to, now);
siz[now] += siz[edge[i].to];
if(siz[son[now]] < siz[ edge[i].to ])
son[now] = edge[i].to;
}
}
void DFS2(int now,int Top)
{
top[now] = Top;
nid[now] = ++cnt;
nw[nid[now]] = w[now];
if(son[now])
DFS2(son[now], Top);
else
return;
for(int i = head[now]; i; i = edge[i].Next)
{
if(edge[i].to != fa[now] && edge[i].to != son[now])
DFS2(edge[i].to, edge[i].to);
}
}
// 建线段树
struct SegmentTree
{
int l,r;
long long dat;
long long add;
} t[N<<2];
void bulid(int l,int r,int p)
{
t[p].l = l;
t[p].r = r;
if(l == r)
{
t[p].dat = nw[l];
return;
}
int mid = (l + r) / 2;
bulid(l,mid,p*2);
bulid(mid+1,r,p*2+1);
t[p].dat = t[p*2].dat + t[p*2+1].dat;
}
void spread(int p)
{
if(t[p].add&&t[p].l!=t[p].r)
{
int mid=(t[p].l+ t[p].r)/2;
t[p*2].add += t[p].add;
t[p*2+1].add += t[p].add;
t[p*2].dat += (mid-t[p].l+1)*t[p].add;
t[p*2+1].dat += (t[p].r-mid)*t[p].add;
}
t[p].add = 0;
}
void change(int l,int r,int add,int p)
{
if(l <= t[p].l && t[p].r <= r)
{
t[p].add += add;
t[p].dat += (t[p].r-t[p].l+1)*add;
return ;
}
spread(p);
int mid = (t[p].l + t[p].r) / 2;
if(l <= mid)
change(l,mid,add,p*2);
if(mid < r)
change(mid+1,r,add,p*2+1);
t[p].dat = t[p*2].dat + t[p*2+1].dat;
}
long long ask(int l,int r,int p)
{
if(l <= t[p].l && t[p].r <= r)
return t[p].dat;
spread(p);
int mid = (t[p].l + t[p].r) / 2;
long long dat=0;
if(l <= mid)
dat += ask(l,mid,p*2);
if(mid < r)
dat += ask(mid+1,r,p*2+1);
return dat;
}
// 利用LCA->最短路操作
int LCA(int x,int y,int op,int z)
{
if(op==2)//sum
{
ans = 0;
while(top[x] != top[y])
{
if(d[top[x]] < d[top[y]])
swap(x,y);
ans += ask(nid[top[x]],nid[x],1);
x = fa[top[x]];
}
if(d[x] > d[y])
swap(x,y);
ans += ask(nid[y],nid[x],1);
return ans;
}
else//change
{
while(top[x] != top[y])
{
if(d[top[x]] < d[top[y]])
swap(x,y);
change(nid[top[x]],nid[x],z,1);
x = fa[top[x]];
}
if(d[x] > d[y])
swap(x,y);
change(nid[x],nid[y],z,1);
return 0;
}
}
// 子树操作
long long asksontree(int x)
{
return ask(nid[x],nid[x]+siz[x]-1,1);
}
void changesontree(int x,int add)
{
change(nid[x],nid[x]+siz[x]-1,add,1);
}
signed main()
{
cin>>n>>m>>r>>MOD;
for(int i = 1; i<= n; i++)
cin >> w[i];
for(int i = 1,f,t; i < n; i++)
{
cin>>f>>t;
add(f,t);
add(t,f);
}
cnt=0;
DFS1(r,0);
DFS2(r,r);
bulid(1,n,1);
for(int i=1,op,l,r,add;i<=m;i++)
{
cin>>op>>l;
if(op!=4)
{
cin>>r;
if(op==1)
{
cin>>add;
LCA(l,r,op,add);
} else
if(op==2)
cout<<LCA(l,r,op,0)%MOD<<endl; else
if(op==3)
changesontree(l,r);
}
else
cout<<asksontree(l)%MOD<<endl;
}
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...