题目链接:震波
这道题有一种紫荆花之恋的既视感→_→
于是我果断写了点分+treap,结果这道题卡常数……treap被生生卡掉了……
于是我一气之下把treap改成了线段树,然后发现空间似乎多了一个log……接着仔细想了想,发现由于每棵子树长度是连续的一段,那么我只需要控制一下每棵线段树维护的区间,那么每棵线段树所用空间就是\(O(size)\)的了,于是总空间就变成了\(O(n\log n)\)……
还是讲讲做法吧。首先,两个点之间的路径必然会经过他们在点分树上的$lca$(这不是废话么)。我们把点分的结构维护下来,对每个节点\(u\)开一棵线段树,维护它的子树中到\(u\)距离为\(x\)的所有点的点权和。然后查询时一路往上跳,在线段树中查询即可。
但是这样显然是会算重的。于是我没对每个节点再维护一棵线段树,维护每个点到$father_u$(\(u\)在点分树上的父亲)的距离,跳的时候加加减减就做完了。当然这里省略了很多细节……留给写这道题的人自己去发现。
还有没有异或上次的\(ans\)导致无限RE……不开心……
下面贴代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define maxn 100010 #define MAXN maxn*50 using namespace std; typedef long long llg; int n,m,a[maxn],fa[maxn],siz[maxn],dx[maxn]; int head[maxn],next[maxn<<1],to[maxn<<1],tt,dep[maxn]; int dis[maxn][30],d[maxn],ld,du[maxn],co[maxn][2]; int val[MAXN],zhi[MAXN],sumv[MAXN],ans; int s[MAXN][2],rt[maxn][2],R,Z,_sum; bool vis[maxn]; int getint(){ int w=0;bool q=0; char c=getchar(); while((c>‘9‘||c<‘0‘)&&c!=‘-‘) c=getchar(); if(c==‘-‘) c=getchar(),q=1; while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w; } void link(int x,int y){ to[++tt]=y;next[tt]=head[x];head[x]=tt; to[++tt]=x;next[tt]=head[y];head[y]=tt; } void add(int &x,int l,int r){ if(!x) x=++tt; int u=x; sumv[u]+=Z; int mid; while(l!=r){ mid=(l+r)>>1; if(R<=mid) u=(s[u][0]?s[u][0]:s[u][0]=++tt),r=mid; else u=(s[u][1]?s[u][1]:s[u][1]=++tt),l=mid+1; sumv[u]+=Z; } } void query(int u,int l,int r){ int mid=(l+r)>>1;if(!u) return; if(r<=R){_sum+=sumv[u];return;} query(s[u][0],l,mid); if(R>mid) query(s[u][1],mid+1,r); } void dfs2(int u,int now){ vis[u]=1; siz[u]=1; dx[u]=0; d[++ld]=u; du[ld]=now; for(int i=head[u],v;v=to[i],i;i=next[i]) if(!vis[v]) dfs2(v,now+1),siz[u]+=siz[v],dx[u]=max(dx[u],siz[v]); vis[u]=0; } void dfs1(int x,int ff){ ld=0; dfs2(x,0); int k=0; for(int i=1,u;u=d[i],i<=ld;i++){ dx[u]=max(dx[u],siz[x]-siz[u]); if(dx[u]<dx[k]) k=u; } ld=0; dfs2(k,0); vis[k]=1; fa[k]=ff; dep[k]=dep[ff]+1; for(int i=1,u;u=d[i],i<=ld;i++){ co[k][0]=max(co[k][0],du[i]); co[k][1]=max(co[k][1],dis[u][dep[ff]]); } for(int i=1,u;u=d[i],i<=ld;i++){ Z=a[u]; R=dis[u][dep[k]]=du[i],add(rt[k][0],0,co[k][0]); if(ff) R=dis[u][dep[ff]],add(rt[k][1],1,co[k][1]); } for(int i=head[k],v;v=to[i],i;i=next[i]) if(!vis[v]) dfs1(v,k); } int main(){ File("a"); n=getint(); m=getint(); dx[0]=n+1; for(int i=1;i<=n;i++) a[i]=getint(); for(int i=2;i<=n;i++) link(getint(),getint()); tt=0; dfs1(1,0); while(m--){ int ty=getint(),x=getint()^ans,y=getint()^ans; if(!ty) ans=0; for(int u=x,d=dep[x];u;u=fa[u],d--){ if(!ty) R=y-dis[x][d],_sum=0,query(rt[u][0],0,co[u][0]),ans+=_sum; else R=dis[x][dep[u]],Z=y-a[x],add(rt[u][0],0,co[u][0]); if(fa[u]) if(!ty) R=y-dis[x][d-1],_sum=0,query(rt[u][1],1,co[u][1]),ans-=_sum; else R=dis[x][dep[fa[u]]],Z=y-a[x],add(rt[u][1],1,co[u][1]); } if(ty) a[x]=y; else printf("%d\n",ans); } return 0; }
原文:http://www.cnblogs.com/lcf-2000/p/6366586.html