hdu 5221 Occupation

Topic:

Each point of a tree has a weight. There are three operations.

1. Walk from x node to y node and take out the weights of the points in the path.

2 Subtract the weight of x node

3 The values of all nodes of the subtree with x as the root node are taken out.


Query once after each operation what the value is now taken out.


Ideas for solving problems:


Introduction Tree Section + Line Section Tree Title

The first time I wrote tree dissection, I wrote a wrong place wa several times.

 while(ty!=tx)
    {
        if(deep[tx]>deep[ty]) //The deeper ones should be tx and ty, not x and y.
        {
           update(1, 1, n, tid[top[x]], tid[x], 1);      
           x=fa[top[x]],  tx=top[x];
        }
        else
        {
            update(1, 1, n, tid[top[y]], tid[y], 1);
            y=fa[top[y]],  ty=top[y];
        }
    }

The dfs order can number the nodes on the tree, and the tree section can make the node numbers on a chain continuous. Then when we need the weights of the paths of two points, we can make the chain of two points rise continuously until they are on the same chain. Because of the nature of the tree section, this process only needs logn times at most, which is an optimization in time.

The first operation is to use tree section to find the continuous numbering interval that we need to update, and then to use segment tree to maintain. Specific I will not talk about, look at the video of Sister Qing Xuejie is clear.

The second operation is the single point updating of the common segment tree.

Third, because the dfs order on a sub-tree must also be continuous, maintenance is also simple.


Code:

#include <bits/stdc++.h>
#define ps push_back
#define lson o<<1
#define rson o<<1|1
#define LL long long 

using namespace std;
const int maxn=1e5+5;
struct p
{
    LL x;
    int lazy;
    LL  sum;
    void init()
    {
        x=0; 
        lazy=-1;
    }
}t[maxn<<4];
int re[maxn];
int son[maxn];
int fa[maxn];
int top[maxn];
int deep[maxn];
int tid[maxn];
int siz[maxn];
vector<int>edg[maxn];
LL val[maxn];
int cnt, n;
void dfs1(int x, int f)
{
    int i, j;
    fa[x]=f;
    son[x]=-1;
    siz[x]=1;
    for(i=0; i<(int)edg[x].size(); i++)
    {
        if(edg[x][i]!=f)
        {
            dfs1(edg[x][i], x);
            siz[x]+=siz[edg[x][i]];
            if(son[x]==-1||siz[son[x]]<siz[edg[x][i]])
            {
                son[x]=edg[x][i];
            }
        } 
    }
    return;
}

void dfs2(int x,  int TOP, int de)
{
    re[cnt]=x, tid[x]=cnt++, top[x]=TOP, deep[x]=de;   

    int i;
    if(son[x]!=-1)
    {
        dfs2(son[x], TOP, de+1);
    }
    for(i=0; i<(int)edg[x].size(); i++)
    {
        if(edg[x][i]!=fa[x] && edg[x][i]!=son[x])
        {
            dfs2(edg[x][i], edg[x][i], de+1);       
        }
    }
    return;
}

void update(int o, int l, int r, int ll, int rr, int x)
{
    if(ll<=l && r<=rr)
    {
        if(x==0)t[o].x=0;
        else t[o].x=t[o].sum,t[o].lazy=x;        
        return;
    }

    if(t[o].lazy!=-1)
    {
        t[lson].x=t[lson].sum;
        t[rson].x=t[rson].sum;
        t[lson].lazy=t[rson].lazy=t[o].lazy;
        t[o].lazy=-1; 
    }
    
    int mid=(l+r)>>1;
    
    if(ll<=mid)update(lson, l, mid, ll, rr, x);
    if(rr>mid)update(rson, mid+1, r, ll, rr, x);

    t[o].x=t[lson].x+t[rson].x;

 //   printf("%d %d %d\n", l, r, t[o].x);
    return;
}


void UPD(int x, int y)
{
    int ty=top[y], tx=top[x];
    while(ty!=tx)
    {
//        printf("%d %d %d %d\n", x, tx, y, ty);
        if(deep[tx]>deep[ty])
        {
        //    printf("l,r %d %d %d\n", top[x], tid[top[x]], tid[x]);
           update(1, 1, n, tid[top[x]], tid[x], 1);      
           x=fa[top[x]],  tx=top[x];
        }
        else
        {
            update(1, 1, n, tid[top[y]], tid[y], 1);
            y=fa[top[y]],  ty=top[y];
        }
    }


      //  printf("%d %d\n", x, y);
        if(deep[x]<deep[y])
        {
           update(1, 1, n, tid[x], tid[y], 1);      
        }
        else
        {
     //       printf("l,r %d %d\n", tid[y], tid[x]);
            update(1, 1, n, tid[y], tid[x], 1);
        }
        return;
}


void build(int o, int l, int r)
{
    t[o].init();

    if(l==r)
    {
        t[o].sum=val[re[l]];
        return;
    }

    int mid=(l+r)>>1;
    build(lson, l, mid);
    build(rson, mid+1, r);

    t[o].sum=t[lson].sum+t[rson].sum;

    return;
}

int main()
{
    int m, i, j;
    cin>>m;
    while(m--)
    {
        scanf("%d", &n);
        for(i=1; i<=n; i++)
        {
            scanf("%lld", &val[i]);
            edg[i].clear();
        }
        int x, y;
        for(i=1; i<n; i++)
        {
            scanf("%d%d", &x, &y);
            edg[x].ps(y);
            edg[y].ps(x);
        }

        cnt=1;
        dfs1(1, 0);
        dfs2(1, 1, 1);

//        for(i=1; i<=n; i++)printf("%d %d\n", son[i], tid[i]);printf("\n");
        build(1, 1, n);

        int q, op;
        scanf("%d", &q);
        
        while(q--)
        {
            scanf("%d", &op);
            if(op==1)
            {
                scanf("%d%d", &x, &y);
                UPD(x, y);        
                printf("%lld\n", t[1].x);
            }  
            else if(op==2)
            {
                scanf("%d", &x);
                update(1, 1, n, tid[x], tid[x], 0);
                printf("%lld\n", t[1].x);
            }
            else 
            {
                scanf("%d", &x);
                update(1, 1, n, tid[x], tid[x]+siz[x]-1, 1);
                printf("%lld\n", t[1].x);
            }
        }
    }    
}

Posted by xisle on Mon, 01 Jul 2019 11:40:40 -0700