bzoj 3626 LCA (tree chaining)

Title:

Ideas:

More interesting tree chain division
First , for the depth of two points lca, we find that it is the overlapping part of the line connecting the two points and the root, then we can first dye all the points from one point to the root, and then use Another point is to see how many points in the root are dyed,
and then think about how to deal with so many intervals. According to what we said before, we can regard all points in [l,r] as the first point, and z as the first point. The second point, so we can ask questions offline, and then we can query while putting the point in

Mistakes and Reflections:

l can be 0, bzoj sometimes does not give very detailed data

Code:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
const int N = 50100;
const int mod= 201314;

struct edge{
    int to,next;
}e[N*2];

vector<int> ans[N];
vector<pair<int,int> > need[N];
int segtree[N*4],lazy[N*4];
int tot,tid,q,n;
int top[N],si[N],fa[N],first[N],son[N],depth[N],id[N],val[N],rnk[N];


void addedge(int x,int y){
    e[tot].to=y;
    e[tot].next=first[x];
    first[x]=tot++;
    e[tot].to=x;
    e[tot].next=first[y];
    first[y]=tot++;
}

void dfs1(int now,int bef,int dep){
    fa[now]=bef;
    depth[now]=dep;
    si[now]=1;
    for(int i=first[now];i!=-1;i=e[i].next)
        if(e[i].to!=bef){
            dfs1(e[i].to,now,dep+1);
            si[now]+=si[e[i].to];
            if(son[now]==-1) son[now]=e[i].to;
            else son[now]=si[e[i].to]>si[son[now]]?e[i].to:son[now];
        }
}

void dfs2(int now,int tp){
    top[now]=tp;
    id[now]=tid++;
    if(son[now]!=-1) dfs2(son[now],tp);
    for(int i=first[now];i!=-1;i=e[i].next)
        if(e[i].to!=fa[now]&&e[i].to!=son[now])
            dfs2(e[i].to,e[i].to);
}

void init(){
    tot=0; tid=0;
    memset(first,-1,sizeof(first));
    memset(son,-1,sizeof(son));
}

void pushup(int rt){
    segtree[rt]=segtree[rt<<1]+segtree[rt<<1|1];
}

void pushdown(int l,int r,int rt){
    if(lazy[rt]){
        int m=(l+r)/2;

        segtree[rt<<1]+=(m-l+1)*lazy[rt];
        segtree[rt<<1]%=mod;
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1]%=mod;

        segtree[rt<<1|1]+=(r-m)*lazy[rt];
        segtree[rt<<1|1]%=mod;
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt<<1|1]%=mod;

        lazy[rt]=0;
    }
}

void add(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r){
        segtree[rt]+=r-l+1;
        segtree[rt]%=mod;
        lazy[rt]++;
        lazy[rt]%=mod;
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if(m>=L) add(L,R,lson);
    if(m<R) add(L,R,rson);
    pushup(rt);
}

int query(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r)
        return segtree[rt];
    pushdown(l,r,rt);
    int m=(l+r)/2;
    int ans=0;
    if(m>=L) ans+=query(L,R,lson);
    ans%=mod;
    if(m<R) ans+=query(L,R,rson);
    ans%=mod;
    pushup(rt);
    return ans;
}
int cal(int L,int R){
    int f1=top[L],f2=top[R];
    int ans=0;
    while(f1!=f2)
    {
        if(depth[f1]<depth[f2])
        {
            swap(f1,f2);
            swap(L,R);
        }
        ans+=query(id[f1],id[L],0,tid-1,1);
        ans%=mod;
        L=fa[f1];
        f1=top[L];
    }
    if(depth[L]>depth[R]) swap(L,R);
    ans+=query(id[L],id[R],0,tid-1,1);
    ans%=mod;
    return ans;
}
void up(int L,int R){
    int f1=top[L],f2=top[R];
    while(f1!=f2){
        if(depth[f1]<depth[f2]){
            swap(f1,f2);
            swap(L,R);
        }
        add(id[f1],id[L],0,tid-1,1);
        L=fa[f1];
        f1=top[L];
    }
    if(depth[L]>depth[R]) swap(L,R);
    add(id[L],id[R],0,tid-1,1);
}
int main(){
    init();
    scanf("%d%d",&n,&q);
    for(int i=1,u;i<n;i++){
        scanf("%d",&u);
        addedge(u,i);
    }
    dfs1(0,0,1);
    dfs2(0,0);
    for(int i=1;i<=n;i++) rnk[id[i]]=i;

    for(int i=0;i<q;i++){
        int ta,tb,tc; scanf("%d%d%d",&ta,&tb,&tc);
        if(ta)
            need[ta-1].push_back(make_pair(tc,i));
        else
            ans[i].push_back(0);

        need[tb].push_back(make_pair(tc,i));

    }
    for(int i=0;i<n;i++){
        up(0,i);
        for(int j=0;j<need[i].size();j++){
            int an=cal(0,need[i][j].fi);
            ans[need[i][j].se].push_back(an);
        }
    }
    for(int i=0;i<q;i++){
        if(ans[i][1]<ans[i][0])
            printf("%d\n",ans[i][1]+mod-ans[i][0]);
        else
            printf("%d\n",ans[i][1]-ans[i][0]);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324677022&siteId=291194637