mxqz,样例都过不了/px

P3178 [HAOI2015] 树上操作

```cpp #include<bits/stdc++.h> using namespace std; #define int long long #define debug cout<<"Here?"<<endl; const int maxn=300010; int n,m,tot=0,h[maxn],val[maxn],lazytag[maxn],tree[maxn*3],sum[maxn],size[maxn],cnt[maxn]; int id[maxn],dep[maxn],fa[maxn],top[maxn],big[maxn]; struct Edge{ int to; int next; }e[maxn]; void add(int u,int v) { e[++tot].to=v; e[tot].next=h[u]; h[u]=tot; } void build(int k,int l,int r) { if(l==r) { tree[k]=cnt[l]; return ; } int mid=(l+r)>>1; build(k>>1,l,mid); build(k>>1|1,mid+1,r); sum[k]=sum[k<<1]+sum[k<<1|1]; } void dfs1(int now,int f) { dep[now]=dep[f]+1; size[now]=1; fa[now]=f; for(int i=h[now];i;i=e[i].next) { int to=e[i].to; if(to==f) continue; dfs1(to,now); size[now]+=size[to]; if(big[now]==-1||size[to]>size[big[now]]) big[now]=to; } return ; } int num=0; void dfs2(int now,int tp) { top[now]=tp; id[now]=++num; if(big[now]==-1) return ; // cout<<now<<"de"<<endl; cnt[num]=val[now]; if(big[now]) dfs2(big[now],tp); for(int i=h[now],to=e[i].to;i;i=e[i].next) { if(to==fa[now]) continue; if(to==big[now]) continue; dfs2(to,to); } } void pushdown(int k,int len) { lazytag[k<<1]+=lazytag[k]; lazytag[k<<1|1]+=lazytag[k]; sum[k<<1]+=lazytag[k]*(len-(len>>1)); sum[k<<1|1]+=lazytag[k]*(len>>1); lazytag[k]=0; } void update(int k,int l,int r,int x,int y,int p) { if(x<=l&&r<=y) { lazytag[k]+=p; sum[k]+=(y-x+1)*p; return ; } if(lazytag[k]) pushdown(k,r-l+1); int mid=(l+r)>>1; if(x<=mid) update(k<<1,l,mid,x,y,p); if(y>mid) update(k<<1|1,mid+1,r,x,y,p); sum[k]=sum[k<<1]+sum[k<<1|1]; } int res=0; void find(int k,int l,int r,int x,int y) { if(l>=x&&r<=y) { res+=sum[k]; return ; }else{ int mid=(l+r)>>1; //debug // if(lazytag[k]) pushdown(k,r-l+1); //加上这行就无法运行了/px if(x<=mid) find(k<<1,l,mid,x,y); if(y>mid) find(k<<1|1,mid+1,r,x,y); } // return res; } int query(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); //debug find(1,1,n,id[top[x]],id[x]); ans+=res; x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); res=0; find(1,1,n,id[x],id[y]); // cout<<"qqqq"<<1<<' '<<n<<' '<<id[2]<<' '<<id[3]<<endl; ans+=res; return ans; } signed main() { memset(big,-1,sizeof big); int xx,yy; cin>>n>>m; for(int i=1;i<=n;i++) scanf("%lld",&val[i]); for(int i=1;i<n;i++) scanf("%lld%lld",&xx,&yy),add(xx,yy),add(yy,xx); dfs1(1,0); // for(int i=1;i<=n;i++) // { // cout<<big[i]<<'w'<<endl; // } dfs2(1,1); build(1,1,n); while(m--) { int opt; cin>>opt; if(opt==1) { scanf("%lld%lld",&xx,&yy); update(1,1,n,id[xx],id[xx],yy); } if(opt==2) { scanf("%lld%lld",&xx,&yy); update(1,1,n,id[xx],id[xx]+size[id[xx]]-1,yy); } if(opt==3) { scanf("%lld",&xx); cout<<query(1,xx)<<endl; } } // for(int i=1;i<=n;i++) cout<<id[i]<<endl; return 0; } // id x ```
by Yukinoshita_Yukino @ 2022-01-28 08:10:51


~~find 函数开成 int 的不好吗拿全局变量存答案还容易清零不彻底~~
by StarLbright40 @ 2022-01-28 08:23:30


@[Maksur](/user/173323) 不是你这个res为啥不在每次find后都清零呢?不清零你第二次find之后res的值就是前两次的总和,然后你的ans就会再把第一次的累加一遍
by __zzy__ @ 2022-01-28 09:03:08


还有你的dfs2写的什么鬼....没有重儿子的叶节点也要先 ```cnt[num]=val[now]```再返回啊,下面的那个for循环令我懵逼,你的to初始化一次之后再也没变过,循环了个啥
by __zzy__ @ 2022-01-28 09:04:48


update里面也是,当前被覆盖的区间是 $[l,r]$ ,但是你增加的值是整个修改区间的长度*增加的值```p```
by __zzy__ @ 2022-01-28 09:06:26


还有下面对子树进行修改的时候,$x$的子树大小就是 $size[x]$ 啊,你重新标号之后又没改size数组,怎么能用第二遍的标号去调用
by __zzy__ @ 2022-01-28 09:08:38


除了我说的这几个还有错,样例仍然没过,我再改改。 建议重新学习树剖
by __zzy__ @ 2022-01-28 09:09:36


@[__zzy__](/user/478552) wssb,谢谢大佬/bx
by Yukinoshita_Yukino @ 2022-01-28 09:11:22


@[Maksur](/user/173323) CaO你厉害啊,线段树建树错了....我拿我AC代码对了半天差点没看出来..... 建树的那个是 ```build(k<<1,l,mid),build(k<<1|1,mid+1,r)``` 你写了个 ```build(k>>1,l,mid),build(k>>1|1,mid+1,r)```
by __zzy__ @ 2022-01-28 09:27:24


恭喜0号节点荣获MVP
by __zzy__ @ 2022-01-28 09:27:46


| 下一页