标题是不是押韵了RT,记录,本地用的TDM-GCC 9.2.0 64-bit Debug,把 -Wall -Wextra -Wconversion -Waggressive-loop-optimizations什么的全加上了,一个 Warning 都不给我报,下载了 #1 的数据非但运行成功,甚至结果都是对的,想要 Debug 不知从何下手,也不知道是真正的 RE 还是 WA,想请大佬们帮忙看一眼。
本地在没有开大栈空间的时候会在 dfs 时爆栈,不知是否是这个原因。
第一篇题解做法,tonowx 这棵线段树的第 i 位维护 x 的子树中与 x 距离为 i 的结点的权值和,tofax 的第 i 位则维护 x 的子树中与 fax 距离为 i 的结点的权值和(以上距离均指原树上的)。代码中RMQ暴力求 lca 和原树两点距离的部分复制而来,可以保证基本没有问题。线段树也大概率不会出锅,除非空间开小。
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
void tomax(int &x,int y){if(x<y) x=y;}
const int N=1e5+1.14514;
int tonow[N],tofa[N],tot;
namespace sgt{
struct node{
int s,ls,rs;
#define s(x) t[x].s
#define ls(x) t[x].ls
#define rs(x) t[x].rs
}t[N*80];
int req(int &x){return x?x:x=++tot;}
void ins(int now,int ln,int rn,int p,int x){//在 p 位置加上 x
if(ln==rn) return s(now)+=x,void();
int mid=ln+rn>>1;
if(p<=mid) ins(req(ls(now)),ln,mid,p,x);
else ins(req(rs(now)),mid+1,rn,p,x);
s(now)=s(ls(now))+s(rs(now));
}
int qry(int now,int ln,int rn,int l,int r){//求 [l,r] 的区间和
if(l<=ln&&rn<=r) return s(now);
int mid=ln+rn>>1,res=0;
if(l<=mid) res+=qry(ls(now),ln,mid,l,r);
if(r>mid) res+=qry(rs(now),mid+1,rn,l,r);
return res;
}
}
vector<int> vc[N];
int fa[N],rt;
namespace ot{
vector<int> vc[N];
//-------------------------------------------lca distance on tree
int dep[N],lst[N],ide[N<<1],cnt;
void dfs(int now,int fa){
dep[now]=dep[fa]+1;
lst[now]=++cnt;ide[cnt]=now;
for(int v:vc[now]) if(v!=fa){
dfs(v,now);lst[now]=++cnt;ide[cnt]=now;
}
}
int s[N<<1][20],pos[N<<1][20];
void build(int n){
for(int i=1;i<=n;++i) s[i][0]=dep[ide[i]],pos[i][0]=i;
for(int lg=1;1<<lg<=n;++lg) for(int i=1;i<=n-(1<<lg)+1;++i){
if(s[i][lg-1]<s[i+(1<<lg-1)][lg-1]) s[i][lg]=s[i][lg-1],pos[i][lg]=pos[i][lg-1];
else s[i][lg]=s[i+(1<<lg-1)][lg-1],pos[i][lg]=pos[i+(1<<lg-1)][lg-1];
}
}
int lca(int x,int y){
if(lst[x]>lst[y]) swap(x,y);
x=lst[x];y=lst[y];int lg=log2(y-x+1);
return ide[s[x][lg]<s[y-(1<<lg)+1][lg]?pos[x][lg]:pos[y-(1<<lg)+1][lg]];
}
int dis(int x,int y){
return dep[x]+dep[y]-(dep[lca(x,y)]<<1);
}
//----------------------------------------------
int siz[N],totsiz,mnmx,rt;bool vis[N];
void fndrt(int now,int lst){//找中心
siz[now]=1;int mxsiz=0;
for(int v:vc[now]) if(v!=lst&&!vis[v]){
fndrt(v,now);tomax(mxsiz,siz[v]);siz[now]+=siz[v];
}
tomax(mxsiz,totsiz-siz[now]);
if(mxsiz<mnmx) rt=now,mnmx=mxsiz;
}
void resiz(int now,int lst){//重新求 siz
siz[now]=1;for(int v:vc[now]) if(v!=lst&&!vis[v]) resiz(v,now),siz[now]+=siz[v];
}
int buildnt(int now){//建出点分树
mnmx=114514;fndrt(now,0);vis[now=rt]=1;resiz(now,0);
for(int v:vc[now]) if(!vis[v]){
totsiz=siz[v];v=buildnt(v);
::vc[now].push_back(v);fa[v]=now;
}return ::rt=now;
}
}
int w[N],n;
void toursub(int now,int tp){//求tp的 tonow 和 tofa
sgt::ins(tonow[tp],0,n,ot::dis(now,tp),w[now]);
if(fa[tp]) sgt::ins(tofa[tp],0,n,ot::dis(now,fa[tp]),w[now]);
for(int v:vc[now]) toursub(v,tp);
}
void bdalltree(int now){//预处理出所有结点的 tonow 和 tofa
toursub(now,now);for(int v:vc[now]) bdalltree(v);
}
int upd(int x,int y){
int t=x,ad=y-w[t],lstd=0;w[t]=y;
while(fa[x]){
sgt::ins(tonow[x],0,n,lstd,ad);
sgt::ins(tofa[x],0,n,lstd=ot::dis(t,fa[x]),ad);
x=fa[x];
}
sgt::ins(tonow[x],0,n,lstd,ad);
return 114514;
}
int qry(int x,int y){
int res=sgt::qry(tonow[x],0,n,0,y),t=x;
while(fa[t]){
int d=ot::dis(x,fa[t]);
if(d<=y) res+=sgt::qry(tonow[fa[t]],0,n,0,y-d)-sgt::qry(tofa[t],0,n,0,y-d);
t=fa[t];
}
return res;
}
int main()
{
int m,x,y,f,ans=0;scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",w+i);
for(int i=1;i<n;++i){
scanf("%d%d",&x,&y);
ot::vc[x].push_back(y);
ot::vc[y].push_back(x);
}
ot::dfs(1,0);
ot::build(n<<1);
ot::totsiz=n;
ot::buildnt(1);
for(int i=1;i<=n;++i) tonow[i]=++tot,tofa[i]=++tot;
bdalltree(rt);
while(m--){
scanf("%d%d%d",&f,&x,&y);
x^=ans;y^=ans;
f?upd(x,y):printf("%d\n",ans=qry(x,y));
}
}
不胜感激。