LCA题解

LCA题解

神奇化简题,谁看得出这是树剖。

首先,\(lca\)的祖宗对\(lca\)都有贡献,我们不妨将\(0\)\(lca\)路径的权值都加\(1\),则\(lca\)\(deep\)就为\(0\)\(lca\)的路径权值和

\(\sum_{i=l}^{r}deep[lca_{i}]=\sum_{i=l}^{r}\sum_{j=lca_{i}}^{j\epsilon path(0,lca_{i})}w[j]\)

我们想想在不会\(lca\)的时候如何暴力搞两个点\(x\)\(y\)的l\(ca\)

我们可以明确深度大于\(lca\)的点对于\(lca\)不会有贡献,且\(deep[x]>=deep[lca]\)

不妨将我们不妨将\(0\)\(x\)路径的权值都加\(1\)\(deep[lca]=\sum_{i=y}^{i\epsilon path(0,y)}w[i]\)

感性理解一下吧

如此我们需要枚举\(i\)\(l\)\(r\),将\(0\)\(i\)路径的权值都加\(1\),\(\sum_{i=l}^{r}deep[lca(i,z)]=\sum_{i=z}^{i\epsilon path(0,z)}w[i]\)

这样一次查询时间复杂度为\(O(n*logn*logn)\)

\(q\)次询问。

我们想,每一次询问都把线段树清空太浪费了,区间\([l,r]\)可以差分为\([1,r]-[1,l-1]\)

将询问拆成\([1,l-1]\)\([1,r]\)两部分,按右端点排序即可.

代码:

#include
#define lc (x<<1)
#define rc (x<<1|1) 
using namespace std;
const int N=60006,inf=1e9,mod=201314;
int n,m,t1,t2,t3,cnt=0,dfn=0,tot=0,f[N],a[N],d[N],son[N],siz[N],num[N],top[N],lazy[N<<2],w[N<<2],head[N],ans[N];
struct xd{int i,flag,x,y;}q[N<<1];
struct edge{int nxt,to;}e[N<<1];
inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
void dfs(int x){
     d[x]=d[f[x]]+1,siz[x]=1; int maxt=0,maxa=-1;
     for(int i=head[x];i;i=e[i].nxt){
            dfs(e[i].to),siz[x]+=siz[e[i].to];
            if(maxa>1))%mod)%mod,w[rc]=(w[rc]+lazy[x]*(len>>1)%mod)%mod,lazy[x]=0;}
void update(int l,int r,int p,int q,int x,int y){
     if(p<=l&&r<=q){w[x]=(w[x]+(r-l+1)*y%mod)%mod,lazy[x]=(lazy[x]+y)%mod; return;}
     pushdown(x,r-l+1);
     int mid=l+r>>1;
     if(p<=mid) update(l,mid,p,q,lc,y);
     if(q>mid) update(mid+1,r,p,q,rc,y);
     w[x]=(w[lc]+w[rc])%mod;
}
int query(int l,int r,int p,int q,int x){
     if(p<=l&&r<=q) return w[x];
     pushdown(x,r-l+1);
     int mid=l+r>>1,ans=0;
     if(p<=mid) ans=query(l,mid,p,q,lc);
     if(q>mid) ans=(ans+query(mid+1,r,p,q,rc))%mod;
     return ans;
}
void lj_update(int x,int y){
    while(top[x]!=top[y]){
         if(d[top[x]]d[y]) swap(x,y);
    update(1,n,num[x],num[y],1,1); 
}
int lj_query(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
         if(d[top[x]]d[y]) swap(x,y);
    ans=(ans+query(1,n,num[x],num[y],1))%mod; 
    return ans;
}
bool cmp(xd u,xd v){return u.x

你可能感兴趣的:(LCA题解)