社区讨论
不用dfs序神秘思路RE+MLE0分求条
P3384【模板】重链剖分 / 树链剖分参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mlvl52qn
- 此快照首次捕获于
- 2026/02/21 08:33 3 周前
- 此快照最后确认于
- 2026/02/23 19:20 2 周前
样例对的但是70MB
MLE+RE
主要思路是一个点的子树里面链编号连续
开线段树记每个链被总体加的值
对每个链建的线段树
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
#define i128 __int128_t
struct zuoti{
int l;
int r;
int ls,rs;
i128 len;
i128 sum;
i128 tag;
zuoti(){
l=0;r=0;sum=0;tag=0;
ls=0;rs=0;len=0;
}
}xds1[400005],xds2[400005];
int n,q,rt,M;
int fa[100005];
int a[100005];
bool vis[100005];
int dep[100005],MXdep[100005],MXL[100005];
int idx=1;
vector<int>tmp[100005],e[100005];
vector<int>L[100005];
int inL[100005],xb[100005];
bool cmp(int aa,int bb){
return MXdep[aa]>MXdep[bb];
}
void dfs(int x){
// cout << "HYW";
vis[x]=1;
for(int i=0;i<tmp[x].size();i++){
if(vis[tmp[x][i]]==0)e[x].push_back(tmp[x][i]);
}
if(e[x].size()==0){
MXdep[x]=dep[x];
return;
}
for(int i=0;i<e[x].size();i++){
fa[e[x][i]]=x;
dep[e[x][i]]=dep[x]+1;
dfs(e[x][i]);
MXdep[x]=max(MXdep[x],MXdep[e[x][i]]);
}
sort(e[x].begin(),e[x].end(),cmp);
}
void dfs1(int x){
// cout << "DEB";
L[idx].push_back(x);
inL[x]=idx;xb[x]=L[idx].size()-1;
if(e[x].size()==0){
MXL[x]=idx;
return;
}
for(int i=0;i<e[x].size();i++){
dfs1(e[x][i]);
MXL[x]=max(MXL[x],MXL[e[x][i]]);
idx++;
}
}
vector<zuoti>xds[100005];
// 1 -> idx-1 lian 0 ZD 1e5+1 TAG
void pushup(int id,int x){
xds[id][x].sum=xds[id][xds[id][x].ls].sum+xds[id][xds[id][x].rs].sum;
}
void mktree(int id,int x,int l,int r){
// cout << "HYW" << id << " " << x << " " << l << " " << r << "\n";
zuoti tmpp;
tmpp.len=0;tmpp.ls=0;tmpp.rs=0;tmpp.l=l;tmpp.r=r;tmpp.sum=0;tmpp.tag=0;
xds[id].push_back(tmpp);//x==xb
if(l==r){
xds[id][x].sum=a[L[id][l]];
return;
}
int mid=l+r>>1;
xds[id][x].ls=xds[id].size();
mktree(id,xds[id].size(),l,mid);
xds[id][x].rs=xds[id].size();
mktree(id,xds[id].size(),mid+1,r);
pushup(id,x);
}
void mktree1(int x,int l,int r){
xds1[x].l=l;
xds1[x].r=r;
if(l==r){
xds1[x].sum=xds[l][1].sum;
xds1[x].len=L[l].size()-1;
return;
}
int mid=l+r>>1;
mktree1(x<<1,l,mid);
mktree1(x<<1|1,mid+1,r);
xds1[x].sum=xds1[x<<1].sum+xds1[x<<1|1].sum;
xds1[x].len=xds1[x<<1].len+xds1[x<<1|1].len;
}
void mktree2(int x,int l,int r){
xds2[x].l=l;
xds2[x].r=r;
if(l==r){
xds2[x].len=L[l].size()-1;
return;
}
int mid=l+r>>1;
mktree2(x<<1,l,mid);
mktree2(x<<1|1,mid+1,r);
xds2[x].len=xds2[x<<1].len+xds2[x<<1|1].len;
}
void pushdown(int id,int x){
if(xds[id][x].tag==0)return;
int tg=xds[id][x].tag;
int ls=xds[id][x].ls,rs=xds[id][x].rs;
xds[id][ls].tag+=tg;
xds[id][ls].sum+=tg*(xds[id][ls].r-xds[id][ls].l+1);
xds[id][rs].tag+=tg;
xds[id][rs].sum+=tg*(xds[id][rs].r-xds[id][rs].l+1);
xds[id][x].tag=0;
}
void modify(int id,int x,int askl,int askr,int k){
int l=xds[id][x].l,r=xds[id][x].r;
if(askl<=l&&r<=askr){
xds[id][x].tag+=k;
xds[id][x].sum+=k*(r-l+1);
return;
}
pushdown(id,x);
int mid=l+r>>1;
if(mid>=askl)modify(id,xds[id][x].ls,askl,askr,k);
if(mid<askr)modify(id,xds[id][x].rs,askl,askr,k);
pushup(id,x);
}
int query(int id,int x,int askl,int askr){
int l=xds[id][x].l,r=xds[id][x].r;
if(askl<=l&&r<=askr){
return xds[id][x].sum;
}
pushdown(id,x);
int sum=0;
int mid=l+r>>1;
if(mid>=askl)sum+=query(id,xds[id][x].ls,askl,askr);
if(mid<askr)sum+=query(id,xds[id][x].rs,askl,askr);
return sum%M;
}
//void pushdown1(int x){
// if(xds1[x].tag==0)return;
// int tg=xds1[x].tag;
// xds1[x<<1].tag+=tg;xds1[x<<1|1].tag+=tg;
// xds1[x<<1].sum+=tg*xds1[x<<1].len;
// xds1[x<<1|1].sum+=tg*xds1[x<<1|1].len;
// xds1[x].tag=0;
//}
void modify1(int x,int askl,int askr,int k){
int l=xds1[x].l,r=xds1[x].r;
if(askl<=l&&r<=askr){
xds1[x].sum+=k;
return;
}
// pushdown1(x);
int mid=l+r>>1;
if(mid>=askl)modify1(x<<1,askl,askr,k);
if(mid<askr)modify1(x<<1|1,askl,askr,k);
xds1[x].sum=xds1[x<<1].sum+xds1[x<<1|1].sum;
}
void pushdown2(int x){
if(xds2[x].tag==0)return;
int tg=xds2[x].tag;
xds2[x<<1].tag+=tg;xds2[x<<1|1].tag+=tg;
xds2[x<<1].sum+=tg*xds2[x<<1].len;
xds2[x<<1|1].sum+=tg*xds2[x<<1|1].len;
xds2[x].tag=0;
}
i128 query2(int x,int askl,int askr){
// cout << x << " " << askl << " " << askr << endl;
i128 sum=0;
if(askl>askr)return sum;
int l=xds2[x].l,r=xds2[x].r;
if(askl<=l&&r<=askr){
// cout << "666";
if(askl==askr)return xds2[x].sum/xds2[x].len;
else return xds2[x].sum;
}
pushdown2(x);
int mid=l+r>>1;
if(mid>=askl)sum+=query2(x<<1,askl,askr);
if(mid<askr)sum+=query2(x<<1|1,askl,askr);
return sum%M;
}
void modify2(int x,int askl,int askr,int k){
if(askl>askr)return ;
int l=xds2[x].l,r=xds2[x].r;
if(askl<=l&&r<=askr){
xds2[x].sum+=k*xds2[x].len;
xds2[x].tag+=k;
return ;
}
pushdown2(x);
int mid=l+r>>1;
if(mid>=askl)modify2(x<<1,askl,askr,k);
if(mid<askr)modify2(x<<1|1,askl,askr,k);
xds2[x].sum=xds2[x<<1].sum+xds2[x<<1|1].sum;
}
void solve(int x,int y,int k){
while(inL[x]!=inL[y]){
int tx=L[inL[x]][1],ty=L[inL[y]][1];
if(dep[tx]<dep[ty]){int t=x;x=y;y=t;tx=L[inL[x]][1],ty=L[inL[y]][1];}
modify(inL[x],1,1,xb[x],k);
modify1(1,inL[x],inL[x],k*xb[x]);
x=fa[tx];
}
if(xb[x]>xb[y]){int t=x;x=y;y=t;}
modify(inL[x],1,xb[x],xb[y],k);
modify1(1,inL[x],inL[x],k*(xb[y]-xb[x]+1));
}
i128 SUM(int x,int y){
i128 sum=0;
while(inL[x]!=inL[y]){
int tx=L[inL[x]][1],ty=L[inL[y]][1];
if(dep[tx]<dep[ty]){int t=x;x=y;y=t;tx=L[inL[x]][1],ty=L[inL[y]][1];}
// modify(inL[x],1,1,xb[x],k);
// modify1(1,inL[x],inL[x],k*xb[x]);
sum+=query(inL[x],1,1,xb[x]);
sum+=query2(1,inL[x],inL[x])*xb[x];
x=fa[tx];
}
if(xb[x]>xb[y]){int t=x;x=y;y=t;}
sum+=query(inL[x],1,xb[x],xb[y]);
sum+=query2(1,inL[x],inL[x])*(xb[y]-xb[x]+1);
return sum%M;
}
void solve2(int x,int k){
int ln=L[inL[x]].size()-1;
modify(inL[x],1,xb[x],ln,k);
modify1(1,inL[x],inL[x],k*(ln-xb[x]+1));
modify2(1,inL[x]+1,MXL[x],k);
}
i128 SUM2(int x){
// cout << "HYW";
int ln=L[inL[x]].size()-1;
i128 sum=0;
sum+=query(inL[x],1,xb[x],ln);
// cout << "HYW";
sum+=query2(1,inL[x],inL[x])*(ln-xb[x]+1);
// cout << "HYW";
sum+=query2(1,inL[x]+1,MXL[x]);
// cout << "HYW";
// cout << "HYW";
return sum%M;
}
signed main(){
cin >> n >> q >> rt >> M;
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int i=1;i<n;i++){
int u,v;
cin >> u >> v;
tmp[u].push_back(v);
tmp[v].push_back(u);
}
dfs(rt);
for(int i=0;i<=n;i++){
L[i].push_back(0);
xds[i].push_back(zuoti());
}
dfs1(rt);
// cout << idx << " ";
for(int i=1;i<=idx;i++){
if(L[i].size()==1){
idx=i;break;
}
}
// cout << idx << endl;
// Sleep(11451);
for(int i=1;i<idx;i++){
mktree(i,1,1,L[i].size()-1);
}
mktree1(1,1,idx-1);//Lians sum
mktree2(1,1,idx-1);//Lians tag
for(int i=1;i<=q;i++){
int opt,x,y,z;
cin >> opt;
if(opt==1){
cin >> x >> y >> z;
solve(x,y,z);
}
else if(opt==2){
cin >> x >> y;
int tmpp=SUM(x,y);
tmpp=(tmpp%M+M)%M;
cout << tmpp << endl;
}
else if(opt==3){
cin >> x >> z;
solve2(x,z);
}
else {
cin >> x;
int tmpp=SUM2(x);
tmpp=(tmpp%M+M)%M;
cout << tmpp << endl;
}
}
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...