uoj#295. [ZJOI2017] Line segment tree (multiplication on the tree)

Put the code first, and update it later.

============================= 2018.3.21UPD ===================== =========
The topic is here

practice

First of all, you need to understand the operation process of the zkw line segment tree. (If you don’t understand Baidu, look at it)
Probably starting from two leaf nodes, maintaining two pointers, one pointing to l One to the left, one to point r The one on the right keeps jumping up. Then imitate this process and also operate on this generalized line segment tree, draw a picture to find out, suppose l 1 the leaf node u r + 1 the leaf node v , a line segment [ l , r ] will be divided into several small line segments that are exactly u l c a ( u , v ) the right brothers of all left sons on the chain, and v l c a ( u , v ) The left brother of all right sons on the chain.
Be sure to draw! ! ! Watch more! ! !
It's easy once you find this out. press a chain l c a Divide it into two halves, then vigorously classify and discuss, multiply on the tree, and there are too many details. for example, l = 1 and r = n cases require special handling, and u When the location is more special, it also needs to be judged.
It is recommended to push and watch qwq by yourself. (I was thinking of qwq by myself at the time, and I felt that I came up with a zjoi question and I was cute! Cute! Da!

code

/*
*   zkw线段树的科技;
*   一堆细节;
*   考试一定要对拍!不对拍会死的!
*/
#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x); i<=(y); i++)
#define per(i,x,y) for (int i=(x); i>=(y); i--)
#define N 400010
#define ll long long
using namespace std;
ll read(){
    char ch=getchar(); ll x=0; int op=1;
    for (; !isdigit(ch); ch=getchar()) if (ch=='-') op=-1;
    for (; isdigit(ch); ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*op;
}
int n,m,tot,rt,now,clk,a[N],f[N][20],pos[N],in[N],out[N];
ll g[N],h[N],f1s[N],f2s[N],gs[N],hs[N],ans,dep[N];
struct seg{
    int l,r,ls,rs,mid;
    seg(){ l=r=ls=rs=mid=0; }
}tr[N];
void build(int &o,int l,int r,int d,int fa,bool fl){
    o=++tot; in[o]=++clk; tr[o].l=l; tr[o].r=r; dep[o]=d; f[o][0]=fa;
    if (!fl){//左儿子
        g[o]=g[fa]+d; gs[o]=gs[fa]+1;
        h[o]=h[fa]; hs[o]=hs[fa];
        f1s[o]=f1s[fa]+d-1; f2s[o]=f2s[fa];
    } else{
        g[o]=g[fa]; gs[o]=gs[fa];
        h[o]=h[fa]+d; hs[o]=hs[fa]+1;
        f1s[o]=f1s[fa]; f2s[o]=f2s[fa]+d-1;
    }
    if (l==r){ pos[l]=o; out[o]=++clk; return; } int k=a[now]; tr[o].mid=k;
    if (l<k) now++; build(tr[o].ls,l,k,d+1,o,0);
    if (k+1<r) now++; build(tr[o].rs,k+1,r,d+1,o,1);
    out[o]=++clk;
}
void print_tree(int u){
    printf("id: %d, l=%d, r=%d\n",u,tr[u].l,tr[u].r);
    if (tr[u].ls) print_tree(tr[u].ls);
    if (tr[u].rs) print_tree(tr[u].rs);
}
int lca(int x,int y){
    if (dep[x]<dep[y]) swap(x,y);
    int tmp=dep[x]-dep[y];
    per (i,18,0) if (tmp>>i&1) x=f[x][i];
    if (x==y) return x;
    per (i,18,0) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
bool isanc(int x,int y){ return in[x]<=in[y] && out[x]>=out[y]; }
int main(){
    /*freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);*/
    n=read();
    rep (i,1,n-1) a[i]=read();
    m=read();
    now=1; build(rt,1,n,0,0,1);
    rep (j,1,18) rep (i,1,tot) f[i][j]=f[f[i][j-1]][j-1];
    while (m--){
        int u=read(),l=read(),r=read(),x,y,z,w,v,tmp;
        ans=0;
        if (l==1 && r==n){ printf("%d\n",dep[u]); continue; }
        x=pos[l-1]; y=pos[r+1]; tmp=lca(x,y); z=tr[tmp].ls; if (l==1 || r==1) z=1;
        if (l!=1){
            w=lca(x,u);
            if (isanc(w,z)){
                ll sum=gs[x]-gs[z];
                ans+=g[x]-g[z]+sum*dep[u]-2ll*sum*dep[w];
                if (w==z && isanc(tr[w].rs,u)) ans-=2;
            } else{
                ll sum=gs[x]-gs[w];
                ans+=g[x]-g[w]+sum*dep[u]-2ll*sum*dep[w];
                sum=gs[w]-gs[z];
                ans+=g[w]-g[z]+sum*dep[u]-2ll*(f1s[w]-f1s[z]);
                if (isanc(tr[w].rs,u)) ans-=2;
            }
        }
        z=tr[tmp].rs; if (l==1 || r==1) z=1;
        if (r!=n){
            w=lca(y,u);
            if (isanc(w,z)){
                ll sum=hs[y]-hs[z];
                ans+=h[y]-h[z]+sum*dep[u]-2ll*sum*dep[w];
                if (w==z && isanc(tr[w].ls,u)) ans-=2;
            } else{
                ll sum=hs[y]-hs[w];
                ans+=h[y]-h[w]+sum*dep[u]-2ll*sum*dep[w];
                sum=hs[w]-hs[z];
                ans+=h[w]-h[z]+sum*dep[u]-2ll*(f2s[w]-f2s[z]);
                if (isanc(tr[w].ls,u)) ans-=2;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

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