bzoj4196

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/syh0313/article/details/88948018

为数不多的一遍过的树链剖分

安装时询问,修改到root的链      删除时询问,修改子树

跑了8s好刺激qwq

/**************************************************************

    Problem: 4196

    User: syh0313

    Language: C++

    Result: Accepted

    Time:8076 ms

    Memory:15392 kb

****************************************************************/

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <string>

#define lch a[n].lc

#define rch a[n].rc

using namespace std;

const int maxn=100010;

struct da{int lc,rc,l,r,sum,tag;}a[maxn<<2];

int n,q,st[maxn],to[maxn],nt[maxn],topt,x,root,cnt;

int dep[maxn],rem[maxn],si[maxn],fa[maxn];

int dfn[maxn],line[maxn],dfn_num,top[maxn];

bool f[maxn];

char s[20];

void add(int x,int y)

{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}

void dfs1(int x,int de)

{

    f[x]=1; dep[x]=de; si[x]=1; int p=st[x],ma=0;

    while (p)

    {

        if (!f[to[p]])

        {

            dfs1(to[p],de+1);

            fa[to[p]]=x; si[x]+=si[to[p]];

            if (si[to[p]]>ma) {ma=si[to[p]]; rem[x]=to[p];}

        }

        p=nt[p];

    }

}

void dfs2(int x)

{

    f[x]=1; if (rem[fa[x]]==x) top[x]=top[fa[x]];else top[x]=x;

    dfn[x]=++dfn_num; line[dfn_num]=x;

    if (rem[x]) dfs2(rem[x]);

    int p=st[x];

    while (p)

    {

        if (!f[to[p]]) dfs2(to[p]);

        p=nt[p];

    }

}

void updata(int n) {a[n].sum=a[lch].sum+a[rch].sum;}

void build_tree(int &n,int l,int r)

{

    n=++cnt; a[n].l=l; a[n].r=r;  a[n].tag=-1;

    if (l==r)  return;

    int mid=(l+r)>>1;

    build_tree(lch,l,mid); build_tree(rch,mid+1,r);

    updata(n);

}

void pushdown(int n)

{

    if (a[n].tag==-1) return;

    a[lch].sum=(a[lch].r-a[lch].l+1)*a[n].tag;

    a[rch].sum=(a[rch].r-a[rch].l+1)*a[n].tag;

    a[lch].tag=a[rch].tag=a[n].tag; a[n].tag=-1;

}

void tree_fz(int n,int L,int R,int l,int r,int k)

{

    if (L==l && R==r)

    {a[n].tag=k; a[n].sum=(a[n].r-a[n].l+1)*k; return;}

    pushdown(n);

    int mid=(L+R)>>1;

    if (r<=mid) tree_fz(lch,L,mid,l,r,k);

    else if (l>=mid+1) tree_fz(rch,mid+1,R,l,r,k);

    else tree_fz(lch,L,mid,l,mid,k),tree_fz(rch,mid+1,R,mid+1,r,k);

    updata(n);

}

void qfz(int x,int y,int k)

{

    while (top[x]!=top[y])

    {

        if (dep[top[x]]<dep[top[y]]) swap(x,y);

        tree_fz(root,1,n,dfn[top[x]],dfn[x],k);

        x=fa[top[x]];

    }

    if (dfn[x]>dfn[y]) swap(x,y);

    tree_fz(root,1,n,dfn[x],dfn[y],k);

return;

}

int qury(int n,int L,int R,int l,int r)

{

    if (L==l && R==r) return a[n].sum;

    pushdown(n);

    int mid=(L+R)>>1;

    if (r<=mid) return qury(lch,L,mid,l,r);

    else if (l>=mid+1) return qury(rch,mid+1,R,l,r);

    else return qury(lch,L,mid,l,mid)+qury(rch,mid+1,R,mid+1,r);

    updata(n);

}

int qsum(int x,int y)

{

    int sum=0;

    while (top[x]!=top[y])

    {

        if (dep[top[x]]<dep[top[y]]) swap(x,y);

        sum+=qury(root,1,n,dfn[top[x]],dfn[x]);

        x=fa[top[x]];

    }

    if (dfn[x]>dfn[y]) swap(x,y);

    sum+=qury(root,1,n,dfn[x],dfn[y]);

return sum;

}

int main()

{

    scanf("%d",&n);

    for (int i=1;i<=n-1;i++) scanf("%d",&x),add(x,i);

    dfs1(0,1); memset(f,0,sizeof f); dfs2(0);

    build_tree(root,1,n); scanf("%d",&q);

    while (q--)

    {

        scanf("%s%d",s,&x);

        if (s[0]=='i')

        {

            printf("%d\n",max(0,dep[x]-qsum(0,x)));

            qfz(0,x,1);

        }

        else

        {

            printf("%d\n",qury(root,1,n,dfn[x],dfn[x]+si[x]-1));   

            tree_fz(root,1,n,dfn[x],dfn[x]+si[x]-1,0);

        }

    }

return 0;

}

猜你喜欢

转载自blog.csdn.net/syh0313/article/details/88948018